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

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

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

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

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

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

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

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

Каждая процедура в модуле формы управляемого приложения сопровождается директивой компиляции: &НаКлиенте, &НаСервере, &НаСервереБезКонтекста или &НаКлиентеНаСервереБезКонтекста. Директива определяет, где выполняется код и откуда он доступен. Процедуру &НаКлиенте можно вызвать только с клиента, процедуру &НаСервере — с клиента (через серверный вызов) и с сервера.

Директива &НаСервереБезКонтекста означает, что процедура не имеет доступа к данным формы (реквизитам, элементам, объекту). Такие процедуры удобны для серверных вычислений, но вызывать их извне формы бессмысленно — логичнее вынести их в общий модуль.

Ошибка несовпадения директив — частая причина сообщений вида «Процедура или функция с указанным именем не определена». Например, клиентская процедура не видна в серверном контексте, и компилятор сообщит об этом ещё при сохранении модуля.

Вызов процедуры внутри самого модуля формы

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

Пример типового кода в модуле формы документа:

&НаКлиенте

Процедура РассчитатьСкидку(Команда)

СуммаСкидки = ПолучитьСуммуСкидки(Объект.СуммаДокумента);

Объект.СуммаСкидки = СуммаСкидки;

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

&НаСервере

Функция ПолучитьСуммуСкидки(СуммаДокумента)

Возврат СуммаДокумента * 0.05;

КонецФункции

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

Вызов экспортной процедуры формы из другой формы

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

&НаКлиенте

Процедура ОбновитьНадписьИтога() Экспорт

Элементы.НадписьИтог.Заголовок = "Итого: " + Объект.СуммаДокумента;

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

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

&НаКлиенте

Процедура ОткрытьИОбновить(Команда)

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

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

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

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

Если процедура объявлена без Экспорт, вызов ФормаДокумента.ОбновитьНадписьИтога() выдаст ошибку «Метод объекта не обнаружен». Также учитывайте, что обращение к форме возможно только пока она открыта: после закрытия ссылка на объект формы становится недействительной.

Вызов процедуры формы через оповещения

Штатный и наиболее устойчивый механизм обращения к открытой форме извне — оповещения. Вместо прямого хранения ссылки на форму вызывающий код отправляет оповещение, а форма документа обрабатывает его в обработчике ОбработкаОповещения.

&НаКлиенте

Процедура КомандаИзДругойФормы(Команда)

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

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

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

&НаКлиенте

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

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

ОбновитьНадписьИтога();

КонецЕсли;

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

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

Способы вызова процедуры формы

Прямой вызов через объект формы

Подходит, когда форма гарантированно открыта и у вас есть ссылка на неё. Риск: ошибка при обращении к закрытой форме.

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

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

Перенос логики в общий модуль

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

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

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

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

Если требуется, чтобы после записи документа в модуле объекта что-то обновилось на форме, правильное решение — обработчики ПослеЗаписи на клиенте или оповещение из обработчика записи. Попытка «пробросить» форму на сервер через параметры приведёт к ошибке сериализации или непередаваемому типу.

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

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

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

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

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

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

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

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

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

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

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

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

Остановки нет — проверьте Экспорт, имя метода и директиву компиляции

Вызов экспортной процедуры из другой формы
Норма

Процедура выполняется, форма остаётся открытой

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

Ошибка «Метод объекта не обнаружен» или обращение к закрытой форме

Оповещение между формами
Норма

ОбработкаОповещения получает событие с нужным именем и параметром

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

Событие не приходит — форма закрыта или имя события не совпадает

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

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

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

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

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

Как передать параметры в вызываемую процедуру формы?

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

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

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

Почему вызов работает в отладчике, но не работает у пользователя?

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

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

Используйте ОповеститьОбИзменении(Ссылка) — формы списков штатно реагируют на это оповещение и обновляют данные. Для нестандартной реакции отправьте собственное оповещение и обработайте его в ОбработкаОповещения формы списка.

Итог

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

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