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

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

Как вызвать процедуру из другой формы в 1С

Разбираем, как вызвать процедуру или функцию из другой формы в 1С: Оповестить, ОбработатьОповещение, общие модули, Экспорт. Примеры кода, типичные ошибки и FAQ.

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

Выбор способа зависит от контекста: открыта ли форма-получатель, связаны ли формы иерархией владельца, нужно ли вернуть значение или достаточно уведомления. Ниже разобраны рабочие варианты с примерами кода, их ограничения и типичные ошибки, из-за которых вызов «молча» не срабатывает.

Почему нельзя вызвать процедуру другой формы напрямую

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

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

Способ 1. Вызов через Оповестить и ОбработкаОповещения

Это основной и рекомендуемый способ «вызвать процедуру» в другой форме. Форма-источник отправляет оповещение с уникальным именем события, а форма-получатель в обработчике ОбработкаОповещения проверяет имя и выполняет нужные действия.

Код в форме-источнике (например, после записи элемента):

&НаКлиенте

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

Оповестить("ОбновитьСписокТоваров", Объект.Ссылка, ЭтотОбъект);

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

Код в форме-получателе:

&НаКлиенте

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

Если ИмяСобытия = "ОбновитьСписокТоваров" Тогда

Элементы.Список.Обновить();

КонецЕсли;

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

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

Порядок настройки вызова через оповещение
  1. 1
    В форме-получателе создайте обработчик ОбработкаОповещения с проверкой ИмяСобытия
  2. 2
    Придумайте уникальное имя события, не пересекающееся с типовыми
  3. 3
    В форме-источнике вызовите Оповестить() с этим именем и нужным параметром
  4. 4
    Откройте обе формы и проверьте, что обработчик срабатывает
  5. 5
    Добавьте проверку Источник, если одно событие шлют несколько форм

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

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

&НаКлиенте

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

Оповещение = Новый ОписаниеОповещения("ПослеВыбораТовара", ЭтотОбъект);

ОткрытьФорму("Справочник.Номенклатура.ФормаВыбора", , ЭтотОбъект, , , , Оповещение);

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

&НаКлиенте

Процедура ПослеВыбораТовара(Результат, ДопПараметры) Экспорт

Если Результат <> Неопределено Тогда

Объект.Товар = Результат;

КонецЕсли;

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

Ключевые моменты: процедура-обработчик обязана быть экспортной (слово Экспорт обязательно), её первый параметр — результат закрытия, второй — дополнительные параметры, переданные при создании описания оповещения. Форма-источник при этом ничего не знает о вызывающей: она просто возвращает значение через Закрыть(Результат).

Способ 3. Вынос логики в общий модуль

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

Настройки общего модуля для разных сценариев:

  • флажок Клиент (управляемое приложение) — модуль доступен из клиентского кода форм;
  • флажок Сервер — для серверной логики, работы с базой данных;
  • флажок Вызов сервера — разрешает обращаться к серверному модулю с клиента;
  • процедуры и функции, доступные извне, помечаются словом Экспорт.

Пример вызова из любой формы: ОбщегоНазначенияКлиент.ПоказатьСообщение(Текст) или МойМодульВызовСервера.ПересчитатьИтоги(ДокументСсылка). Помните: в серверном вызове нельзя передавать контекст формы — только сериализуемые данные (ссылки, структуры, массивы).

Сравнение способов вызова

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

Подходит для уведомления открытых форм о событии. Ограничение: закрытая форма событие не получит, возврата значения нет.

ОписаниеОповещения при ОткрытьФорму

Лучший вариант для получения результата из дочерней формы после её закрытия. Работает только в паре «родитель — потомок».

Общий модуль

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

ОповеститьОбИзменении

Стандартный способ для ссылочных объектов: списки сами обновятся после записи элемента без ручных обработчиков.

Способ 4. Стандартное оповещение об изменении объекта

Частая задача «обновить список после записи элемента» вообще не требует ручных оповещений. Платформа умеет сама уведомлять все открытые динамические списки об изменении конкретной ссылки через метод ОповеститьОбИзменении().

&НаКлиенте

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

ОповеститьОбИзменении(Объект.Ссылка);

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

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

Способ 5. Обращение через владельца формы

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

&НаКлиенте

Процедура ПередатьДанные(Команда)

Если ВладелецФормы <> Неопределено Тогда

Оповестить("ДанныеИзПодбора", Новый Структура("Количество", 5), ВладелецФормы);

КонецЕсли;

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

Прямой вызов экспортной процедуры владельца технически возможен в некоторых сценариях, но ненадёжен: владельцем может оказаться элемент формы, а не форма, контекст может быть недоступен, а при переподчинении формы код сломается. Предпочтительнее связка «ОписаниеОповещения + Закрыть(Результат)» — она декларативна и не зависит от внутреннего устройства родительской формы.

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

Самая частая жалоба — «оповещение не срабатывает». Причины почти всегда одни и те же, и проверить их можно за минуту.

Типичные ошибки
01
Опечатка или рассинхрон имени события: в Оповестить одна строка, в ОбработкаОповещения другая — обработчик молча не вызывается.
02
Форма-получатель закрыта в момент отправки: оповещения не ставятся в очередь и не доходят до закрытых форм.
03
Забыто слово Экспорт у процедуры, указанной в ОписаниеОповещения, — платформа не сможет её вызвать.
04
Попытка передать в серверный общий модуль данные формы или элемент управления — ошибка сериализации.
05
Использование Оповестить там, где достаточно ОповеститьОбИзменении: лишний ручной код в каждой форме списка.
06
Вызов клиентской процедуры из серверного контекста: на сервере нет форм и оповещений, Оповестить работает только на клиенте.

Порядок диагностики: поставьте точку останова в ОбработкаОповещения и убедитесь, что обработчик вообще вызывается; если нет — проверьте, открыта ли форма и совпадает ли имя события посимвольно. Затем проверьте условие внутри обработчика: часто событие приходит, но отсекается проверкой Источник или типом параметра.

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

Как проверить, что вызов работает

Срабатывание ОбработкаОповещения
Норма

Точка останова в обработчике останавливает выполнение сразу после Оповестить

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

Обработчик не вызывается — проверяйте имя события и открытость формы

Передача параметра
Норма

В параметре Параметр приходят ожидаемые данные нужного типа

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

Параметр Неопределено или другого типа — смотрите, что передано в Оповестить

Результат из дочерней формы
Норма

Процедура из ОписаниеОповещения получает значение после Закрыть(Результат)

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

Приходит Неопределено — форма закрыта крестиком без возврата значения, обработайте этот случай

Часто задаваемые вопросы

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

Нет. Оповещения получают только открытые формы. Если нужно, чтобы данные «дождались» форму, сохраните их в базе или в параметрах сеанса, а форма пусть прочитает их при создании на сервере или при открытии.

Как вернуть значение из вызванной формы обратно?

Используйте ОткрытьФорму с ОписаниеОповещения: дочерняя форма вызывает Закрыть(Результат), а указанная экспортная процедура родителя получает это значение первым параметром. Для блокирующего сценария подойдёт ОткрытьФормуМодально, но модальный режим в современных конфигурациях нежелателен.

Почему Оповестить не работает в серверной процедуре?

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

Чем ОповеститьОбИзменении отличается от Оповестить?

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

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

Да, но не напрямую из клиентского контекста. В форме создаётся серверная процедура, которая получает объект через РеквизитФормыВЗначение("Объект") и вызывает его экспортный метод. Учтите, что это создаёт отдельный экземпляр объекта — изменения нужно явно записывать и возвращать.

Что делать, если одно событие должны получить несколько форм?

Оповестить рассылается всем открытым формам, поэтому каждая заинтересованная форма просто добавляет обработчик с тем же именем события. Чтобы формы реагировали избирательно, передавайте в параметре структуру с идентификатором адресата и проверяйте его в обработчике.

Итог

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

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