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