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