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