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