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

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

Как получить реквизит формы в модуле объекта 1С

Способы получить реквизит формы из модуля объекта в 1С: через параметры, структуру, ДополнительныеСвойства и другие механизмы. Примеры кода и типичные ошибки.

Модуль объекта в 1С выполняется в контексте самого объекта — документа, справочника, обработки, — и не имеет прямого доступа к форме, из которой объект был открыт или записан. Форма и объект существуют в разных контекстах, и платформа специально разделяет их, чтобы логика данных не зависела от интерфейса. Поэтому прямой синтаксис вида ЭтаФорма.РеквизитФормы в модуле объекта недоступен — переменная ЭтаФорма там просто не определена.

Тем не менее задача передать данные из формы в модуль объекта возникает постоянно: например, нужно заполнить табличную часть по выбранному на форме значению, учесть флажок, установленный пользователем, или передать результат сложного расчёта, выполненного на клиенте. Платформа предлагает несколько законных механизмов для этого — через параметры обработчиков, свойство ДополнительныеСвойства, структуру параметров и программный вызов методов формы.

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

Почему модуль объекта не видит реквизиты формы

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

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

Понимание этого разделения важно, потому что попытки «дотянуться» до формы из объекта обходными путями приводят к ошибкам вида «Переменная не определена» или к хрупкому коду, ломающемуся при записи объекта вне формы — например, при обмене данными, фоновом задании или программной записи из другого модуля.

Способ 1. Передача через ДополнительныеСвойства

Самый распространённый и рекомендуемый механизм — заполнить ДополнительныеСвойства объекта перед записью, а в модуле объекта прочитать их. В модуле формы перед вызовом записи объект доступен через реквизит формы (обычно Объект), и у него можно установить дополнительные свойства.

Пример кода в модуле формы:

&НаКлиенте

Процедура ЗаписатьСПараметром(Команда)

ЗаписатьСПараметромНаСервере();

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

&НаСервере

Процедура ЗаписатьСПараметромНаСервере()

ОбъектДанных = РеквизитФормыВЗначение("Объект");

ОбъектДанных.ДополнительныеСвойства.Вставить("ВыбранныйСклад", СкладНаФорме);

ОбъектДанных.Записать();

ЗначениеВРеквизитФормы(ОбъектДанных, "Объект");

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

В модуле объекта значение читается в любом обработчике записи:

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

ВыбранныйСклад = Неопределено;

Если ДополнительныеСвойства.Свойство("ВыбранныйСклад", ВыбранныйСклад) Тогда

// Используем значение, переданное из формы

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

Строка.Склад = ВыбранныйСклад;

КонецЦикла;

КонецЕсли;

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

Обязательно используйте проверку Свойство("Имя", Значение) с двумя параметрами: если объект записывается программно, из обмена или фонового задания, свойства в структуре не будет, и обращение напрямую вызовет ошибку. Такой защитный код делает объект устойчивым к записи вне формы.

Порядок действий для передачи значения
  1. 1
    В модуле формы получите объект через РеквизитФормыВЗначение("Объект")
  2. 2
    Заполните ДополнительныеСвойства нужными значениями через Вставить()
  3. 3
    Вызовите Записать() у объекта
  4. 4
    В модуле объекта в обработчике ПередЗаписью или ПриЗаписи прочитайте свойство через Свойство() с проверкой
  5. 5
    Верните объект в форму через ЗначениеВРеквизитФормы, если нужно обновить отображение

Способ 2. Передача через параметры обработчиков записи

Некоторые события формы позволяют вмешаться до того, как управление уйдёт в модуль объекта. Например, в обработчике формы ПередЗаписью (модуль формы, сервер) у вас есть доступ и к реквизитам формы, и к записываемому объекту через параметр ТекущийОбъект. Это удобная точка, чтобы перенести значения формы в объект или в его ДополнительныеСвойства.

&НаСервере

Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)

ТекущийОбъект.ДополнительныеСвойства.Вставить("КомментарийПользователя", КомментарийНаФорме);

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

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

Способ 3. Программное чтение реквизита формы в модуле формы

Иногда задача формулируется шире: нужно не передать одно значение, а получить произвольный реквизит формы по имени, например при написании универсального механизма. В модуле формы это делается обращением по строковому имени: ЭтаФорма[ИмяРеквизита]. Проверить существование реквизита можно, перебрав коллекцию ЭтаФорма.РеквизитыФормы (доступна в серверном контексте формы) или через попытку обращения.

&НаСервере

Функция ПолучитьРеквизитФормыПоИмени(ИмяРеквизита)

Реквизиты = ЭтаФорма.РеквизитыФормы;

Для Каждого Реквизит Из Реквизиты Цикл

Если Реквизит.Имя = ИмяРеквизита Тогда

Возврат ЭтаФорма[ИмяРеквизита];

КонецЕсли;

КонецЦикла;

Возврат Неопределено;

КонецФункции

Полученное значение дальше передаётся в модуль объекта одним из описанных способов — чаще всего через ДополнительныеСвойства. Само по себе чтение реквизита формы возможно только в модуле формы; перенести этот код в модуль объекта нельзя.

Способ 4. Вызов экспортной процедуры объекта из формы

Альтернативный подход — не дожидаться события записи, а явно вызвать экспортный метод объекта из модуля формы, передав значение параметром. Для этого в модуле объекта объявляется экспортная процедура, а в форме объект получается через РеквизитФормыВЗначение, после чего метод вызывается.

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

Процедура ЗаполнитьПоСкладу(Склад) Экспорт

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

Строка.Склад = Склад;

КонецЦикла;

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

// Модуль формы

&НаСервере

Процедура ПрименитьСкладНаСервере()

ОбъектДанных = РеквизитФормыВЗначение("Объект");

ОбъектДанных.ЗаполнитьПоСкладу(СкладНаФорме);

ЗначениеВРеквизитФормы(ОбъектДанных, "Объект");

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

Этот вариант прозрачнее, когда логика не привязана к записи: значение передаётся явным параметром, а не скрытой структурой, и код легче отлаживать. Минус — необходимость модифицировать модуль объекта и помнить о преобразовании РеквизитФормыВЗначение / ЗначениеВРеквизитФормы, которое пересоздаёт данные формы.

Сравнение способов

ДополнительныеСвойства

Подходит для передачи данных в события записи и проведения; работает и из подписок. Требует проверки наличия свойства.

Параметры записи формы

Подходит, когда значение известно в клиентском коде в момент Записать(); нужен промежуточный серверный обработчик формы.

Экспортный метод объекта

Подходит для логики вне записи; явные параметры, но требует доработки модуля объекта и преобразования данных формы.

Типичные ошибки и ограничения

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

Третья ошибка — передача через ДополнительныеСвойства несериализуемых данных: таблиц значений с картинками, COM-объектов, ссылок на элементы формы. ДополнительныеСвойства должны содержать простые типы, ссылки, структуры и массивы из них. Также не стоит забывать, что РеквизитФормыВЗначение — дорогая операция для больших объектов; не вызывайте её в цикле или по каждому нажатию кнопки без необходимости.

Типичные ошибки
01
Обращение к ЭтаФорма в модуле объекта — ошибка компиляции, контекст формы недоступен
02
Чтение ДополнительныеСвойства без проверки Свойство() — падение при программной записи вне формы
03
Передача несериализуемых типов в ДополнительныеСвойства — ошибка при передаче между клиентом и сервером
04
Многократный вызов РеквизитФормыВЗначение в цикле — заметное замедление работы формы
05
Забытый вызов ЗначениеВРеквизитФормы после изменений — форма показывает устаревшие данные

Как проверить, что значение дошло до модуля объекта

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

В отладчике конфигуратора поставьте точку останова в ПередЗаписью модуля объекта и посмотрите содержимое ДополнительныеСвойства — туда попадают и служебные свойства платформы и типовых подсистем, поэтому структура обычно не пустая. Если вашего ключа там нет — проблема на стороне формы, а не объекта.

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

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

Наличие ключа в ДополнительныеСвойства в отладчике
Норма

Ключ присутствует, значение соответствует переданному из формы

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

Ключа нет — Вставить не выполнился или вызван у другого экземпляра объекта

Запись объекта вне формы (обмен, фоновое задание)
Норма

Запись проходит без ошибок благодаря проверке Свойство()

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

Исключение при обращении к отсутствующему свойству

Отображение данных в форме после записи
Норма

Форма показывает актуальные данные объекта

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

Данные устарели — не выполнен ЗначениеВРеквизитФормы

FAQ

Можно ли напрямую обратиться к ЭтаФорма из модуля объекта?

Нет. Модуль объекта выполняется в контексте данных, переменная ЭтаФорма там не определена, и платформа не предоставляет ссылки на форму. Данные из формы передаются через ДополнительныеСвойства, параметры обработчиков или экспортные методы объекта.

Чем ДополнительныеСвойства отличаются от реквизитов объекта?

Реквизиты объекта хранятся в базе данных и описаны в конфигурации. ДополнительныеСвойства — временная структура в памяти, существующая только на время выполнения операции; в базу она не записывается и предназначена для обмена данными между модулями.

Работает ли передача через ДополнительныеСвойства при проведении документа?

Да. Если заполнить ДополнительныеСвойства перед вызовом Записать() с режимом проведения, значения будут доступны и в ОбработкаПроведения, и в ПередЗаписью. Главное — читать их через Свойство() с проверкой, чтобы проведение из других контекстов не падало.

Что делать, если объект записывается стандартной кнопкой «Записать» формы?

Используйте серверный обработчик формы ПередЗаписьюНаСервере: в нём доступен параметр ТекущийОбъект, у которого можно заполнить ДополнительныеСвойства до того, как управление перейдёт в модуль объекта.

Как передать из формы в объект таблицу значений?

Поместите таблицу в ДополнительныеСвойства — таблицы значений сериализуются платформой и нормально передаются между клиентом и сервером. Убедитесь, что в таблице нет несериализуемых колонок. Альтернатива — преобразовать таблицу в массив структур.

Почему после изменений объекта форма показывает старые данные?

РеквизитФормыВЗначение создаёт отдельную копию объекта. После изменений нужно вернуть данные в форму вызовом ЗначениеВРеквизитФормы(ОбъектДанных, "Объект"), иначе отображаемые данные не обновятся.

Итог

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

Модуль объекта не имеет доступа к форме — значения передают через ДополнительныеСвойства с обязательной проверкой Свойство(), через серверные обработчики формы или через экспортные методы объекта. Проверка наличия свойства обязательна, чтобы объект корректно записывался вне формы.