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

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

1С: как обратиться к процедуре формы документа

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

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

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

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

Как устроен модуль формы и почему есть ограничения

Форма документа в управляемом приложении существует только на клиенте. Её модуль компилируется с директивами &НаКлиенте, &НаСервере, &НаСервереБезКонтекста и &НаКлиентеНаСервереБезКонтекста. Это определяет, откуда можно вызвать ту или иную процедуру внутри самой формы, но не решает вопрос внешнего обращения.

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

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

Объявление экспортной процедуры в форме документа

Первый шаг — подготовить саму процедуру. В модуле формы документа объявите её с ключевым словом Экспорт и подходящей директивой компиляции. Если процедура меняет элементы формы или данные формы, используйте &НаКлиенте или &НаСервере в зависимости от логики.

&НаКлиенте

Процедура ОбновитьИтогиПоДокументу(Комментарий = "") Экспорт

// Логика пересчета

ЭтотОбъект.ИтоговаяСумма = РассчитатьИтог();

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

Обратите внимание на порядок: сначала директива, затем Процедура с именем и параметрами, и только потом Экспорт. Частая ошибка — поставить Экспорт перед именем или забыть директиву, из-за чего процедура оказывается недоступной в нужном контексте.

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

Вызов процедуры формы из другой формы

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

// Открываем форму документа и получаем её объект

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

ФормаДокумента = ПолучитьФорму("Документ.РеализацияТоваров.ФормаОбъекта", ПараметрыФормы);

ФормаДокумента.Открыть();

ФормаДокумента.ОбновитьИтогиПоДокументу("Вызов извне");

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

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

Порядок вызова из другой формы
  1. 1
    Объявите процедуру в модуле формы документа с ключевым словом Экспорт
  2. 2
    В вызывающем коде получите объект формы через ПолучитьФорму или ОткрытьФорму
  3. 3
    Сохраните объект формы в переменную
  4. 4
    Вызовите процедуру как метод: ФормаДокумента.ИмяПроцедуры(Параметры)
  5. 5
    Проверьте, что директива компиляции вызываемой процедуры совместима с контекстом вызова

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

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

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

&НаКлиенте

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

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

И Источник = ЭтотОбъект.Объект.Ссылка Тогда

ОбновитьИтогиПоДокументу();

КонецЕсли;

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

Из любого клиентского кода (например, из формы связанной обработки или общего клиентского модуля) событие инициируется так:

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

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

Обращение к форме из общего модуля

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

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

ОбщегоНазначенияКлиент.ВыполнитьДействиеСФормой(ЭтотОбъект);

// В общем модуле (Клиент)

Процедура ВыполнитьДействиеСФормой(Форма) Экспорт

Форма.ОбновитьИтогиПоДокументу();

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

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

Директивы компиляции и контекст вызова

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

Директива процедуры формыМожно вызвать извнеКомментарий
&НаКлиенте + ЭкспортДаОсновной вариант для внешних вызовов
&НаСервере + ЭкспортОграниченноДоступна при обращении к объекту формы, но вызов инициируется с клиента
&НаСервереБезКонтекстаНетВызывается только изнутри формы
&НаКлиентеНаСервереБезКонтекстаНетТолько внутри модуля формы

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

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

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

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

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

Способы выполнить логику формы извне

Экспортная процедура формы

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

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

Подходит для вызова из модуля объекта и между независимыми формами. Нужна проверка источника.

Общий модуль

Подходит для бизнес-логики без привязки к интерфейсу. Самый надёжный и тестируемый вариант.

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

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

Для механизма оповещений убедитесь, что событие доходит: временно добавьте в ОбработкаОповещения вывод имени события через Сообщить или окно предупреждения. Это быстро покажет, теряется ли событие или отсекается проверкой источника.

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

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

Точка останова в экспортной процедуре формы
Норма

Отладчик останавливается при внешнем вызове

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

Вызов не доходит — проверьте Экспорт и объект формы

Параметры внутри процедуры
Норма

Значения соответствуют переданным

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

Параметры пустые — ошибка в порядке или составе аргументов

Реакция на Оповестить
Норма

Обрабатывает только форма нужного документа

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

Реагируют все открытые формы — нет проверки Источника

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

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

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

Почему возникает ошибка «Процедура или функция с указанным именем не определена»?

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

Как вызвать процедуру уже открытой формы, если я не сохранил её объект?

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

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

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

Чем отличается вызов через ПолучитьФорму от ОткрытьФорму?

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

Итог

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

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