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

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

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

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

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

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

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

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

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

Если в модуле объекта написать обращение вида ЭтаФорма.МояПроцедура(), компилятор выдаст ошибку: переменная ЭтаФорма в модуле объекта не определена. Аналогично не сработает попытка обратиться к форме по имени переменной — формы не попадают в область видимости серверного контекста объекта.

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

Способ 1. Получить форму через ПолучитьФорму на клиенте

Если логика запускается с клиента (например, из клиентской процедуры, которая вызывает серверный метод объекта), можно получить форму функцией ПолучитьФорму() и вызвать её экспортную процедуру. Этот способ работает только в клиентском контексте.

// Клиентская процедура

ФормаДокумента = ПолучитьФорму("Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента",

Новый Структура("Ключ", СсылкаНаДокумент));

ФормаДокумента.МояЭкспортнаяПроцедура(Параметр1);

Чтобы процедуру можно было вызвать извне, в модуле формы она должна быть объявлена с ключевым словом Экспорт и иметь директиву компиляции, доступную клиенту, например &НаКлиенте:

&НаКлиенте

Процедура МояЭкспортнаяПроцедура(Параметр1) Экспорт

// логика формы

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

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

Способ 2. Оповещения: Оповестить и обработчик в форме

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

// В форме документа

&НаКлиенте

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

Если ИмяСобытия = "ОбновитьИтогиДокумента" И Источник = Объект.Ссылка Тогда

ПересчитатьИтоги();

КонецЕсли;

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

// На клиенте после записи объекта

Оповестить("ОбновитьИтогиДокумента", , СсылкаНаДокумент);

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

Способ 3. Передать форму как параметр

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

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

&НаКлиенте

Процедура КомандаОбработать(Команда)

Результат = ОбработатьНаСервере(); // вызов серверной логики объекта

Если Результат.Успешно Тогда

ПоказатьРезультатПользователю(Результат); // процедура модуля формы

КонецЕсли;

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

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

Способ 4. Вынести общий код в общий модуль

Часто потребность «вызвать процедуру формы из объекта» возникает потому, что одна и та же логика нужна и там, и там. Правильное решение — перенести её в общий модуль с подходящими флагами («Сервер», «Клиент» или «Вызов сервера») и вызывать из обоих мест.

Флаги общего модуляОткуда доступенТипичное применение
СерверМодули объектов, серверные процедуры формЗапросы, расчеты, проведение
Клиент (обычное/управляемое)Клиентские процедуры формДиалоги, оповещения, работа с интерфейсом
Сервер + Вызов сервераКлиентские процедуры через серверный вызовПолучение данных с клиента

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

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

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

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

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

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

Третья ошибка — забыть Экспорт у процедуры формы. Без него внешний вызов завершится сообщением «Метод объекта не обнаружен». Четвёртая — несовпадение директив компиляции: клиентская процедура не может вызывать процедуру &НаСервере формы напрямую без контекста серверного вызова.

Типичные ошибки
01
ЭтаФорма в модуле объекта — ошибка компиляции, переменная не определена
02
Вызов Оповестить() из серверного модуля объекта — метод недоступен на сервере
03
Процедура формы без Экспорт — ошибка «Метод объекта не обнаружен» при вызове
04
Ожидание, что форма открыта: при записи из обмена или фонового задания формы нет
05
Попытка передать объект формы на сервер — управляемая форма не сериализуется

Проверка результата

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

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

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

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

Процедура формы выполняется, данные обновляются

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

Ошибка «Метод не обнаружен» или тишина без реакции

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

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

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

Ошибка вызова клиентских методов на сервере

Запись через обмен данными
Норма

Обмен проходит штатно

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

Сбой обмена из-за обращения к форме

Итог

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

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

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

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

Нет. Открытие формы — клиентская операция. Из модуля объекта можно только подготовить данные; открытие выполняет клиентский код через ОткрытьФорму() или ОткрытьЗначение().

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

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

Почему ПолучитьФорму() создаёт новую форму вместо использования открытой?

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

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

Стандартный механизм — оповещение о записи: форма списка сама обновляется при событии записи. Для нестандартной реакции отправьте Оповестить("ЗаписанЭлемент", Ссылка) на клиенте после записи и обработайте событие в ОбработкаОповещения формы списка.

Работает ли ЭтотОбъект.ПолучитьФорму() в управляемом приложении?

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