К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как обратиться к реквизиту формы документа в 1С

Как обратиться к реквизиту формы документа в 1С: различия управляемой и обычной формы, Объект, ЭтаФорма, реквизиты объекта и формы, примеры кода и типичные ошибки.

Обращение к реквизиту формы документа — одна из самых частых задач при доработке конфигураций 1С, и одновременно один из главных источников ошибок у начинающих разработчиков. Путаница возникает из-за того, что на форме сосуществуют данные разных типов: реквизиты самого объекта (документа), реквизиты формы, добавленные разработчиком, и элементы управления, которые лишь отображают данные. Обращаться к каждому из этих уровней нужно по-разному.

Ключевой момент: код, который работает в модуле объекта документа, не будет работать в модуле формы, и наоборот. В модуле объекта реквизиты доступны напрямую по имени, а в модуле управляемой формы данные документа доступны через реквизит формы с именем Объект. Понимание этого разделения — основа всей дальнейшей работы.

Ниже разобраны способы обращения к реквизитам в управляемой и обычной форме, работа с табличными частями, программное создание реквизитов формы, а также типичные ошибки с пояснением их причин.

Что нужно понять до написания кода: уровни данных на форме

На форме документа одновременно существуют три разных сущности, которые часто путают. Первая — реквизиты объекта, то есть поля самого документа, описанные в конфигураторе (Номер, Дата, Контрагент и т.д.). В управляемой форме они собраны в главном реквизите формы с именем Объект типа «ДанныеФормыСтруктура».

Вторая сущность — реквизиты формы, которые разработчик добавил самостоятельно через панель «Реквизиты формы» в редакторе формы. Они нужны для служебных целей: хранить флаги, промежуточные итоги, настройки отображения. В базу данных они не записываются и существуют только пока открыта форма.

Третья сущность — элементы формы (поля ввода, надписи, таблицы). Элемент лишь отображает данные и связан с реквизитом через свойство «ПутьКДанным». Обращаться к значению через элемент формы — ошибка: нужно работать с реквизитом, а элемент изменится сам.

Обращение к реквизитам объекта в управляемой форме

В модуле управляемой формы документа обращение к реквизиту объекта выполняется через точку от имени Объект:

&НаКлиенте

Процедура КонтрагентПриИзменении(Элемент)

Если ЗначениеЗаполнено(Объект.Контрагент) Тогда

Объект.Договор = ПолучитьОсновнойДоговор(Объект.Контрагент);

КонецЕсли;

КонецПроцедуры

Здесь Объект.Контрагент — чтение значения, Объект.Договор = ... — запись. Присвоение через Объект на клиенте допустимо и не вызывает обращения к серверу, потому что Объект — это данные формы, а не объект базы данных. Реальная запись в информационную базу произойдёт только при вызове Записать() или при проведении.

Если имя реквизита хранится в переменной (например, приходит параметром), используйте обращение через квадратные скобки:

ИмяРеквизита = "СуммаДокумента";

ТекущееЗначение = Объект[ИмяРеквизита];

Обращение к реквизитам, добавленным на форму вручную

Реквизиты, добавленные через редактор формы (панель «Реквизиты формы» → «Добавить»), доступны в модуле формы напрямую по имени:

&НаКлиенте

Процедура РассчитатьСкидку(Команда)

// ПроцентСкидки — реквизит формы, добавленный вручную

ИтоговаяСумма = Объект.СуммаДокумента * (100 - ПроцентСкидки) / 100;

КонецПроцедуры

Альтернативный синтаксис — через ЭтаФорма: ЭтаФорма.ПроцентСкидки. Оба варианта равнозначны, но явное указание ЭтаФорма улучшает читаемость кода и помогает отличить реквизиты формы от локальных переменных. В серверных процедурах с директивой &НаСервере реквизиты формы доступны так же.

Проверить список реквизитов формы можно в конфигураторе: откройте форму документа, панель «Реквизиты формы». Там видно, какие реквизиты являются данными объекта (иерархия под «Объект»), а какие добавлены вручную. У реквизита также виден флаг «Сохраняемые данные» — он определяет, восстановится ли значение при повторном открытии формы.

Работа с табличными частями документа на форме

Табличная часть документа на управляемой форме доступна как коллекция через Объект.ИмяТабличнойЧасти. Типичные операции — перебор строк, обращение к текущей строке и добавление новой:

&НаКлиенте

Процедура ПересчитатьИтоги(Команда)

Итог = 0;

Для Каждого Строка Из Объект.Товары Цикл

Строка.Сумма = Строка.Количество * Строка.Цена;

Итог = Итог + Строка.Сумма;

КонецЦикла;

КонецПроцедуры

Текущую строку табличной части получают не через Объект, а через элемент формы — таблицу: Элементы.Товары.ТекущиеДанные. Обратите внимание: ТекущиеДанные — это объект типа «ДанныеФормыЭлементКоллекции», доступный только на клиенте. В серверной процедуре строку получают по идентификатору: Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки).

Типичные ошибки
01
Обращение Элементы.Товары.Сумма — элемент формы не содержит значения, значение берут из ТекущиеДанные или из строки коллекции Объект.Товары
02
Передача ТекущиеДанные в серверную процедуру — этот тип не сериализуется, передавайте идентификатор строки
03
Попытка изменить реквизит объекта после проведения документа без отмены проведения — получите ошибку или несогласованные данные

Обращение к реквизитам в обычной форме и в модуле объекта

В обычных формах (толстый клиент, старые конфигурации на 8.2 и ранее) реквизиты документа доступны в модуле формы напрямую по имени, без префикса Объект: достаточно написать Контрагент или Товары.Итог("Сумма"). Форма там жёстко связана с объектом данных, и разделения на «реквизит формы Объект» нет.

В модуле объекта документа (обработчики ПередЗаписью, ОбработкаПроведения и др.) реквизиты также доступны напрямую: ЭтотОбъект.Контрагент или просто Контрагент. Код из модуля формы с префиксом Объект. в модуле объекта работать не будет — там нет такого свойства в этом контексте.

Сравнение вариантов обращения

Управляемая форма

Объект.Реквизит для данных документа, ИмяРеквизита или ЭтаФорма.ИмяРеквизита для реквизитов формы. Работает на клиенте и сервере

Обычная форма

Реквизиты документа доступны напрямую по имени. Только толстый клиент, устаревший подход

Модуль объекта

Реквизиты по имени или через ЭтотОбъект.Реквизит. Используется для логики записи и проведения, без доступа к элементам формы

Вне формы (по ссылке)

Ссылка.Реквизит для чтения; для изменения — Ссылка.ПолучитьОбъект() и затем Записать()

Программное создание и изменение реквизитов формы

Иногда реквизит нужно добавить не в конфигураторе, а программно — например, количество полей зависит от настроек пользователя. Для этого используется метод ИзменитьРеквизиты() в серверном контексте, обычно в обработчике ПриСозданииНаСервере:

&НаСервере

Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Добавляемые = Новый Массив;

ОписаниеТипа = Новый ОписаниеТипов("Число");

Добавляемые.Добавить(Новый РеквизитФормы("СлужебныйИтог", ОписаниеТипа));

ИзменитьРеквизиты(Добавляемые);

КонецПроцедуры

После добавления реквизита для него обычно программно создают элемент формы через Элементы.Добавить() и связывают через свойство ПутьКДанным. Учтите ограничение: ИзменитьРеквизиты() — «тяжёлая» операция, вызывать её нужно один раз при создании формы, а не в обработчиках ожидания или при каждом клике пользователя.

Как проверить, что обращение к реквизиту работает правильно

Самый быстрый способ диагностики — отладчик. Поставьте точку останова в обработчике, откройте форму документа в режиме предприятия и посмотрите в табло значение выражения Объект.ИмяРеквизита. Если реквизит существует, значение отобразится; если имени нет — появится ошибка «Поле объекта не обнаружено».

Вторая частая ситуация — код молча не срабатывает, потому что обработчик не привязан к событию элемента. Проверьте в конфигураторе: у поля ввода в палитре свойств должно быть заполнено событие «ПриИзменении» с именем вашей процедуры. Третья проверка — убедиться, что процедура имеет правильную директиву: клиентская процедура не может вызывать серверные методы напрямую, а серверная не видит Элементы.Товары.ТекущиеДанные.

Контрольные точки

Как проверить результат

Существование реквизита
Норма

В отладчике Объект.ИмяРеквизита показывает значение

Тревожный признак

Ошибка «Поле объекта не обнаружено» — проверьте имя и контекст

Изменение значения
Норма

После присвоения поле на форме обновляется сразу

Тревожный признак

Значение присвоено, но на форме не видно — изменён реквизит, не связанный с элементом

Сохранение данных
Норма

После Записать() значение сохраняется при повторном открытии

Тревожный признак

Значение пропадает — был изменён реквизит формы, а не реквизит объекта

Часто задаваемые вопросы

Как обратиться к реквизиту формы из другой формы?

Напрямую — никак, формы изолированы друг от друга. Передайте значение через параметры при открытии формы (ОткрытьФорму с параметрами), через оповещения (Оповестить / ОбработкаОповещения) или сохраните данные в базе и прочитайте их в другой форме.

Почему возникает ошибка «Поле объекта не обнаружено»?

Чаще всего имя реквизита написано с опечаткой, либо код выполняется не в том контексте: например, в модуле объекта написано Объект.Реквизит вместо просто Реквизит, или в форме обработки используется Объект, которого у неё может не быть. Проверьте имя в конфигураторе и тип модуля, где выполняется код.

Как получить значение реквизита документа, не открывая форму?

Через ссылку: Значение = СсылкаНаДокумент.Контрагент; — платформа сама получит данные из базы. Для изменения используйте ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект(); ДокОбъект.Контрагент = НовоеЗначение; ДокОбъект.Записать();.

Чем реквизит формы отличается от реквизита объекта?

Реквизит объекта описан в конфигураторе у документа и хранится в базе данных. Реквизит формы существует только в памяти, пока форма открыта, и в базу не записывается. На управляемой форме реквизиты объекта собраны внутри главного реквизита формы с именем Объект.

Можно ли обратиться к реквизиту по имени, хранящемуся в строке?

Да, используйте квадратные скобки: Объект[ИмяРеквизита] или ЭтаФорма[ИмяРеквизита]. Это стандартный способ для универсальных алгоритмов, где имя поля заранее неизвестно.

Почему изменение реквизита на форме не сохраняется после записи?

Скорее всего, вы изменили реквизит формы, а не реквизит объекта: данные формы в базу не пишутся. Либо запись выполняется через объект, полученный по ссылке, который перезаписывает изменения, сделанные на форме. Изменяйте Объект.ИмяРеквизита и записывайте документ штатной командой формы.

Итог

Что важно запомнить

В управляемой форме документа данные объекта читаются и изменяются через Объект.ИмяРеквизита, добавленные реквизиты формы — напрямую по имени или через ЭтаФорма. Текущую строку табличной части берут из Элементы.Таблица.ТекущиеДанные, а в базу данные попадают только после записи документа.