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