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