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

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

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

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

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

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

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

Почему прямое обращение невозможно

В управляемом приложении 1С код разделён на клиентский и серверный контексты. Модуль формы с директивой &НаКлиенте исполняется на компьютере пользователя, а модуль объекта — всегда на сервере. Между ними нет прямой видимости: серверный код не имеет доступа к клиентским переменным, реквизитам формы и элементам интерфейса.

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

Поэтому правильный подход — не искать способ «пробить» границу контекстов, а организовать передачу данных так, чтобы модуль объекта получал всё необходимое через свои собственные реквизиты или параметры вызова.

Способ 1. Передать значение реквизита формы через параметр

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

Пример. В форме документа есть реквизит формы КомментарийДляОбработки, который нужен при записи. В модуле формы:

&НаКлиенте

Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)

// Сохраняем значение реквизита формы во временное хранилище

АдресДанных = ПоместитьВоВременноеХранилище(КомментарийДляОбработки, УникальныйИдентификатор);

ПараметрыЗаписи.Вставить("АдресКомментария", АдресДанных);

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

Затем в серверной процедуре формы ПередЗаписьюНаСервере значение извлекается и записывается в реквизит объекта, после чего модуль объекта работает с ним как с обычным своим реквизитом. Такой путь сохраняет независимость объекта от формы.

Порядок действий при передаче через параметр
  1. 1
    Определите, какие данные формы нужны модулю объекта
  2. 2
    В клиентской процедуре формы прочитайте реквизит формы
  3. 3
    Передайте значение через ПараметрыЗаписи или параметр серверной процедуры
  4. 4
    На сервере запишите значение в реквизит объекта или используйте напрямую
  5. 5
    Проверьте запись документа программно, без открытия формы

Способ 2. Обратиться к данным через ЭтаФорма в модуле формы

Часто реальная задача формулируется иначе: нужно не «из модуля объекта достучаться до формы», а из процедуры формы, вызываемой при событиях объекта, получить реквизит формы. Здесь всё просто — в модуле формы доступен объект ЭтаФорма, и к реквизитам формы обращаются напрямую по имени или через ЭтаФорма["ИмяРеквизита"].

&НаСервере

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

// Реквизит формы доступен напрямую

Если ЗначениеЗаполнено(РежимПроведения) Тогда

// логика с использованием реквизита формы

КонецЕсли;

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

Обратите внимание: события ПередЗаписьюНаСервере, ПриЗаписиНаСервере, ПослеЗаписиНаСервере выполняются в модуле формы, но уже на сервере. В них доступны и реквизиты формы, и объект записи через параметр ТекущийОбъект. Это удобная точка для синхронизации данных между формой и объектом.

Способ 3. Получить данные объекта через Объект.Ссылка и запрос

Если из модуля объекта нужны данные, которые логически относятся к самому объекту, но почему-то хранятся как реквизит формы, — правильное решение перенести их в реквизиты объекта. Тогда обращение становится тривиальным: ЭтотОбъект.ИмяРеквизита или просто ИмяРеквизита.

Когда нужны данные других объектов (например, реквизиты связанного документа, отображаемые на форме), в модуле объекта их получают через ссылку и запрос:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Док.Согласующий КАК Согласующий

|ИЗ

| Документ.Заявка КАК Док

|ГДЕ

| Док.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Основание);

Результат = Запрос.Выполнить();

Если Не Результат.Пустой() Тогда

Выборка = Результат.Выбрать();

Выборка.Следующий();

// Выборка.Согласующий — нужное значение

КонецЕсли;

Такой подход надёжен, потому что не зависит от того, открыта форма или нет. Запрос работает при любом способе записи объекта: интерактивном, программном, при обмене данными.

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

Иногда потребность обратиться к реквизиту формы — симптом того, что код находится не в своём месте. Если алгоритм опирается на данные, введённые пользователем на форме, и не нужен при программной записи, его место — в модуле формы, а не в модуле объекта.

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

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

Маршрут решения

Как выбрать подход

Данные нужны только при интерактивной работе пользователяОставьте логику в модуле формы, используйте реквизиты формы напрямую
Данные должны влиять на запись объекта всегдаПеренесите их в реквизиты объекта и обращайтесь через ЭтотОбъект
Нужны данные другого объекта, показанные на формеПолучите их в модуле объекта запросом через ссылку
Нужно передать разовое значение из формы в объектПередайте через ПараметрыЗаписи или параметр серверной процедуры

Работа в обычных формах: особенности

В обычном приложении (толстый клиент) технически возможно получить форму объекта через метод ПолучитьФорму() и обратиться к её элементам. Например, из внешней обработки или из модуля объекта в редких сценариях:

ФормаДок = СсылкаНаДокумент.ПолучитьОбъект().ПолучитьФорму();

Если ФормаДок.Открыта() Тогда

Значение = ФормаДок.ЭлементыФормы.ПолеВвода1.Значение;

КонецЕсли;

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

Типичные ошибки и как их избежать

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

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

Типичные ошибки
01
Обращение к ЭтаФорма из модуля объекта — переменная недоступна в серверном контексте объекта
02
Хранение важных данных в реквизитах формы — при программной записи логика не сработает
03
Проверка открытости формы в обработчиках объекта — код падает при обмене данными
04
Передача на сервер сложных объектов формы — сериализуются только простые типы и структуры

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

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

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

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

Запись через форму
Норма

Данные формы учтены, объект записан корректно

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

Значения реквизитов формы игнорируются или теряются

Программная запись без формы
Норма

Объект записывается без ошибок

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

Ошибка обращения к форме или незаполненным данным

Пустые значения
Норма

Есть проверка на Неопределено и пустую строку

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

Исключение при незаполненных данных

Если все три сценария проходят, архитектура решения верна. Если программная запись падает — в модуле объекта осталась скрытая зависимость от формы, которую нужно найти и устранить.

Итог

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

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

Частые вопросы

Можно ли из модуля объекта узнать, открыта ли форма документа?

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

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

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

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

Поместите таблицу во временное хранилище на клиенте, передайте адрес хранилища в серверную процедуру и извлеките данные методом ПолучитьИзВременногоХранилища. Альтернатива — использовать табличную часть объекта, которая передаётся между контекстами автоматически.

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

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

Можно ли вызвать процедуру модуля формы из модуля объекта?

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