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