Разработка и Конфигурация · 11 мин
Как обратиться к реквизитам формы в 1С
Как обратиться к реквизитам формы в 1С: синтаксис обращения из модуля формы, из внешнего кода, работа с ДанныеФормыСтруктура, типичные ошибки и примеры кода.
Реквизит формы в 1С — это данные, которые хранятся непосредственно в форме и существуют только в течение её жизни. К ним относятся как реквизиты, добавленные разработчиком в конфигураторе, так и основной реквизит формы, связанный с объектом данных (документом, справочником). Умение правильно обращаться к реквизитам формы — базовый навык при доработке управляемых форм, обработке событий и передаче данных между клиентом и сервером.
Главная сложность для начинающих — разница между обращением из модуля самой формы и из внешнего кода, а также особенности работы с реквизитами типа «ДанныеФормыСтруктура», когда данные объекта представлены в форме не напрямую, а через специальную обёртку. Ошибки здесь типичны: обращение к несуществующему имени, попытка прочитать реквизит объекта как реквизит формы, использование серверных методов на клиенте.
Ниже разобраны синтаксис обращения, приёмы работы с основным реквизитом объекта, программное добавление реквизитов, передача данных между формами и способы проверки результата. Все примеры применимы к управляемым формам на платформе 8.3.
Как устроены реквизиты формы и чем они отличаются от реквизитов объекта
Реквизиты формы — это переменные, объявленные в дереве реквизитов формы в конфигураторе или добавленные программно. Они хранятся в контексте формы и исчезают после её закрытия, если их значения не были сохранены специально. Типичные примеры: «Счетчик», «ТекущийПользователь», «ТаблицаЗначенийДляОтображения».
Реквизиты объекта (например, «Номер», «Дата», «Организация» у документа) — это данные, хранящиеся в базе. В управляемой форме объекта они доступны через основной реквизит формы, который обычно называется «Объект» и имеет тип «ДанныеФормыСтруктура». Обращение к ним выглядит как Объект.Организация, а не как прямое обращение к реквизиту формы.
Путаница между этими двумя категориями — самая частая причина ошибок вида «Поле объекта не обнаружено». Если реквизит добавлен в дерево реквизитов формы — обращайтесь к нему напрямую. Если реквизит принадлежит объекту данных — обращайтесь через основной реквизит формы.
Обращение к реквизиту формы из модуля формы
Внутри модуля формы реквизит доступен напрямую по имени. Платформа автоматически включает реквизиты формы в контекст модуля, поэтому можно писать коротко:
&НаКлиенте
Процедура КомандаРассчитать(Команда)
// Прямое обращение к реквизиту формы
Счетчик = Счетчик + 1;
// Или явно через ЭтаФорма
ЭтаФорма.Счетчик = ЭтаФорма.Счетчик + 1;
КонецПроцедуры
Оба варианта равнозначны. Явное обращение через ЭтаФорма предпочтительнее, когда имя реквизита совпадает с именем локальной переменной или когда код нужно сделать более читаемым. В серверных процедурах синтаксис тот же:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ДатаНачала = ТекущаяДатаСеанса();
ЭтаФорма.КомментарийСлужебный = "Форма открыта";
КонецПроцедуры
Обращение к реквизиту объекта (основного реквизита формы) выполняется через имя «Объект»: Объект.Номер, Объект.Товары. Табличные части объекта в форме представлены типом «ДанныеФормыКоллекция», по ним можно итерироваться и обращаться к колонкам по именам.
Как получить значение объекта из реквизита формы на сервере
Основной реквизит формы типа «ДанныеФормыСтруктура» — это не объект базы данных, а его представление. Чтобы вызвать методы объекта (например, Записать(), ПроверитьЗаполнение()) или обратиться к механизмам, требующим настоящего объекта, нужно преобразование:
&НаСервере
Процедура ЗаписатьОбъектНаСервере()
ДокументОбъект = РеквизитФормыВЗначение("Объект");
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");
КонецПроцедуры
Метод РеквизитФормыВЗначение() создаёт объект данных из реквизита формы. После изменений объект возвращают обратно через ЗначениеВРеквизитФормы(), иначе форма не увидит изменений. Если обратное преобразование не выполнить, пользователь продолжит видеть старые данные, а при записи через стандартную команду формы изменения могут быть потеряны.
Обратное преобразование обязательно, если вы изменяли объект. Если объект только читался (например, для проверки), возвращать его в форму не требуется — это сэкономит время сериализации.
- 1В серверной процедуре вызовите РеквизитФормыВЗначение("Объект")
- 2Выполните нужные операции с объектом: изменение реквизитов, проверка, запись
- 3Вызовите ЗначениеВРеквизитФормы(Объект, "Объект"), если данные изменялись
- 4Проверьте в форме, что поля отобразили актуальные значения
Обращение к реквизитам формы из внешнего кода
Когда нужно прочитать или установить реквизит формы из другой формы, общего модуля или обработки, сначала получают сам объект формы. Типичный сценарий — открытие формы и передача ей данных:
&НаКлиенте
Процедура ОткрытьИПередать(Команда)
ПараметрыФормы = Новый Структура("ОрганизацияОтбор", ТекущаяОрганизация);
Форма = ОткрытьФорму("Обработка.ПодборТоваров.Форма", ПараметрыФормы, ЭтаФорма);
// Обращение к реквизиту открытой формы
Форма.РежимПодбора = Истина;
КонецПроцедуры
Функция ПолучитьФорму() также возвращает объект формы, через который доступны её реквизиты. Однако прямое обращение к реквизитам чужой формы — хрупкий приём: если разработчик той формы переименует реквизит, внешний код сломается без предупреждения. Более надёжная альтернатива — передача данных через параметры формы, оповещения (Оповестить / ОбработкаОповещения) или экспортные процедуры модуля формы.
Программное добавление и изменение реквизитов формы
Реквизиты можно создавать динамически, в коде формы. Это нужно, когда состав данных заранее неизвестен — например, при построении формы по настройкам пользователя. Используется метод ИзменитьРеквизиты():
&НаСервере
Процедура ДобавитьРеквизитыНаСервере()
Добавляемые = Новый Массив;
ОписаниеТипа = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(100));
Добавляемые.Добавить(Новый РеквизитФормы("АдресДоставки", ОписаниеТипа, , "Адрес доставки"));
ИзменитьРеквизиты(Добавляемые);
КонецПроцедуры
После добавления реквизит доступен так же, как созданный в конфигураторе: ЭтаФорма.АдресДоставки. Чтобы реквизит появился на форме визуально, нужно дополнительно создать элемент формы через Элементы.Добавить() и связать его с реквизитом через свойство ПутьКДанным.
Метод ИзменитьРеквизиты() доступен только на сервере. Также учтите: при повторном вызове с тем же именем реквизита возникнет ошибка, поэтому перед добавлением стоит проверять существование или удалять старые реквизиты через второй параметр метода (массив удаляемых).
Проверка результата и типичные ошибки
После обращения к реквизиту убедитесь, что значение действительно установлено или прочитано. Простейшая проверка — вывести значение через Сообщить() или посмотреть его в отладчике, поставив точку останова в строке обращения. В отладчике реквизиты формы видны в табло через объект ЭтаФорма.
Признак корректной работы: реквизит читается без исключений, значение соответствует ожидаемому типу, а изменения, сделанные на сервере, видны на клиенте после завершения серверного вызова. Если значение «теряется» между сервером и клиентом — проверьте, не объявлена ли процедура с директивой &НаСервереБезКонтекста: в таких процедурах реквизиты формы недоступны вообще.
Как проверить результат
Значение нужного типа отображается в табло
Ошибка «Поле объекта не обнаружено» или значение Неопределено
Изменённое на сервере значение видно в клиентской процедуре после вызова
На клиенте старое значение — вероятно, использована директива БезКонтекста
После ЗначениеВРеквизитФормы поля формы обновились
Форма показывает прежние данные, изменения потеряны при записи
Частые вопросы
Как обратиться к реквизиту формы из общего модуля?
Напрямую — никак: общий модуль не знает о конкретной форме. Передайте объект формы как параметр в экспортную процедуру общего модуля (для серверных модулей передают ЭтаФорма), и внутри процедуры обращайтесь к реквизитам через этот параметр. Учтите, что тип параметра будет «УправляемаяФорма», и компилятор не проверит существование реквизита заранее.
Почему реквизит формы недоступен в процедуре &НаСервереБезКонтекста?
Директива «БезКонтекста» означает, что на сервер не передаются данные формы — это ускоряет вызов, но лишает доступа к реквизитам и элементам формы. Либо смените директиву на &НаСервере, либо передавайте нужные значения параметрами.
Как передать значение реквизита при открытии другой формы?
Используйте структуру параметров: сформируйте Структуру с нужными ключами, передайте её в ОткрытьФорму(), а в открываемой форме обработайте параметры в ПриСозданииНаСервере через объект Параметры. Это надёжнее, чем запись в реквизиты открытой формы после её создания.
Чем отличается ЭтаФорма от ЭтотОбъект в модуле формы?
В модуле управляемой формы используется ЭтаФорма — она ссылается на объект «УправляемаяФорма». ЭтотОбъект в модулях форм объектов (обычных форм и модулей объектов) ссылается на сам объект данных. В управляемой форме прямого доступа к объекту через ЭтотОбъект нет — только через РеквизитФормыВЗначение().
Как обратиться к табличной части объекта в форме?
Через основной реквизит формы: Объект.Товары — это коллекция типа «ДанныеФормыКоллекция». По ней можно итерироваться циклом «Для Каждого», обращаться к строкам по индексу и читать колонки по именам: Объект.Товары[0].Номенклатура. Для добавления строки используйте Объект.Товары.Добавить().
Можно ли обратиться к реквизиту формы по имени, хранящемуся в строке?
Да, индексное обращение работает: ЭтаФорма[ИмяРеквизита], где ИмяРеквизита — строковая переменная. Это удобно при универсальных обработчиках, когда имя реквизита определяется динамически, например при обходе настроек.
Что важно запомнить
Из модуля формы реквизиты доступны напрямую по имени или через ЭтаФорма; реквизиты объекта — через основной реквизит «Объект». Для работы с объектом на сервере используйте пару РеквизитФормыВЗначение / ЗначениеВРеквизитФормы. Избегайте &НаСервереБезКонтекста, когда нужны данные формы, и передавайте данные между формами через параметры и оповещения, а не прямой записью в чужие реквизиты.