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