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

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

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

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

Модуль объекта и модуль формы в 1С — это разные контексты исполнения с разным набором доступных свойств. Модуль объекта выполняется на сервере при работе с данными (запись, проведение, проверка заполнения), а модуль формы — при отображении и интерактивной работе пользователя. Поэтому прямого доступа к элементам формы, реквизитам формы и её командам из модуля объекта нет: там недоступны свойства Элементы, ЭтаФорма в смысле управляемой формы и клиентские методы интерфейса.

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

Ниже разобраны рабочие способы взаимодействия модуля объекта с формой, ограничения каждого подхода и типичные ошибки, которые приводят к ошибкам вида «Переменная не определена (Элементы)» или «Свойство объекта не обнаружено».

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

Управляемая форма в 1С существует только в контексте клиентского сеанса и реализуется объектом типа УправляемаяФорма. Модуль же объекта компилируется и исполняется в контексте прикладного объекта (документа, справочника) — чаще всего на сервере, причём один и тот же объект может записываться вообще без формы: из обмена данными, фонового задания, внешней обработки или кода другого объекта.

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

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

Способ 1: обработка событий записи в модуле формы

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

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

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

&НаКлиенте

Процедура ПослеЗаписи(ПараметрыЗаписи)

Если Объект.Проведен Тогда

Элементы.ФормаПровести.Доступность = Ложь;

ЭтаФорма.Заголовок = "Документ № " + Объект.Номер + " (проведен)";

КонецЕсли;

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

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

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

Способ 2: передача формы параметром в общий модуль или метод

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

// Общий модуль (клиент или клиент-сервер)

Процедура НастроитьВидимостьПоСтатусу(Форма) Экспорт

Элементы = Форма.Элементы;

Элементы.Комментарий.Видимость = (Форма.Объект.Статус = "НаСогласовании");

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

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

&НаКлиенте

Процедура ПриОткрытии(Отказ)

УправлениеФормойКлиент.НастроитьВидимостьПоСтатусу(ЭтаФорма);

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

Ограничения: параметр типа УправляемаяФорма нельзя передавать на сервер в вызовах, где форма недоступна, и нельзя сохранять ссылку на форму между вызовами — после закрытия формы ссылка станет недействительной. Также общий модуль должен быть скомпилирован с подходящими флагами (Клиент, Сервер), иначе вызов завершится ошибкой компиляции контекста.

Способ 3: сообщения пользователю с привязкой к элементу формы

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

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

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

Если Не ЗначениеЗаполнено(Контрагент) Тогда

Сообщение = Новый СообщениеПользователю;

Сообщение.Текст = "Не заполнен контрагент";

Сообщение.Поле = "Контрагент";

Сообщение.УстановитьДанные(ЭтотОбъект);

Сообщение.Сообщить();

Отказ = Истина;

КонецЕсли;

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

Метод УстановитьДанные() связывает сообщение с объектом, а свойство Поле задаёт путь к реквизиту. Платформа сама находит на открытой форме элемент, связанный с этим реквизитом, и подсвечивает его. Для табличных частей путь указывается с индексом строки, например Товары[2].Количество.

Способ 4: оповещения между объектом и формой

Когда объект записывается программно (из другой формы, обработки, фонового задания), а открытая форма должна обновиться, применяется механизм оповещений: Оповестить() на стороне инициатора и ОбработкаОповещения в модуле формы.

// Инициатор (например, после записи объекта в общем модуле)

Оповестить("ЗаписанДокументРеализация", Новый Структура("Ссылка", ДокументСсылка));

// Модуль формы, которую нужно обновить

&НаКлиенте

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)

Если ИмяСобытия = "ЗаписанДокументРеализация"

И Параметр.Ссылка = Объект.Ссылка Тогда

ЭтаФорма.Прочитать();

Элементы.ГруппаИтоги.Заголовок = "Данные обновлены";

КонецЕсли;

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

Также полезен метод формы ОповеститьОбИзменении(Ссылка) — он рассылает стандартное оповещение об изменении объекта, и все открытые формы этого объекта (списки, формы элемента) автоматически обновляют данные без дополнительного кода.

Сравнение способов взаимодействия с формой

События формы (ПослеЗаписи)

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

СообщениеПользователю с УстановитьДанные

Идеален для ошибок заполнения из модуля объекта. Подсвечивает поле автоматически, но менять свойства элементов не позволяет.

Передача формы параметром

Удобен для переиспользуемого кода настройки формы. Ограничение — только клиентский контекст, нельзя хранить ссылку на форму.

Оповестить / ОбработкаОповещения

Единственный способ уведомить открытые формы при программной записи. Требует стандартизировать имена событий в конфигурации.

Типичные ошибки и как их диагностировать

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

Ошибка «Свойство объекта не обнаружено (ЭтаФорма)» возникает при обращении к ЭтаФорма вне модуля формы. В модуле объекта такого свойства нет; там доступен ЭтотОбъект, но он содержит только данные, а не интерфейс.

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

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

Проверка результата и границы безопасных изменений

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

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

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

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

Запись документа из формы
Норма

Интерфейс обновляется, ошибок нет

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

Ошибки обращения к элементам или форма не реагирует

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

Объект записывается, интерфейсный код не выполняется

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

Ошибки вида 'Переменная не определена' в модуле объекта

Сообщение об ошибке заполнения
Норма

Поле подсвечено, фокус на нём

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

Сообщение без привязки — неверное свойство Поле

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

Итог

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

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

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

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

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

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

Напрямую — никак. Закрытие формы выполняется на клиенте: в модуле формы в обработчике ПослеЗаписи вызовите ЭтаФорма.Закрыть() при выполнении нужного условия, либо используйте Оповестить с командой закрытия и обработайте её в форме.

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

Коллекция Элементы — свойство объекта УправляемаяФорма, который существует только в контексте формы. Модуль объекта исполняется в контексте данных и может работать вообще без интерфейса, поэтому платформа не предоставляет ему доступ к интерфейсным объектам.

Как подсветить поле табличной части из ОбработкаПроверкиЗаполнения?

Заполните у сообщения свойство Поле в формате «Товары[ИндексСтроки].Количество» (индексация с нуля) и вызовите УстановитьДанные(ЭтотОбъект). Платформа найдёт на форме таблицу, связанную с табличной частью, и выделит нужную ячейку.

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

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

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

Подписки на события для логики записи и расширения конфигурации для доработки форм. Так изменения переживают обновления типовой поставки и не требуют снятия конфигурации с полной поддержки.