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

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

Как вызвать обработчик события в 1С

Как вызвать обработчик события в 1С: прямой вызов процедуры, метод Выполнить, подписки на события, вызов серверных обработчиков с клиента. Примеры кода и ошибки.

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

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

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

Как устроены обработчики событий в 1С

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

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

Прямой вызов обработчика по имени

Самый простой и надёжный способ — вызвать процедуру напрямую. Если вызов происходит в том же модуле, достаточно указать имя и передать параметры:

&НаКлиенте

Процедура КомандаПовторить(Команда)

// Программно "нажимаем" кнопку сохранения

КнопкаСохранитьНажатие(Элементы.КнопкаСохранить);

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

Если обработчик находится в другом модуле — например, в общем модуле или модуле объекта — вызов выполняется через точку: ОбщегоНазначения.ОбработатьЗапись(Ссылка); или ДокументОбъект.ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения);. Условие: процедура должна быть экспортной (с ключевым словом Экспорт), иначе она недоступна извне модуля.

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

Динамический вызов через Выполнить и Вычислить

Когда имя обработчика хранится в строке — например, задано в настройках, в дополнительных отчётах и обработках или в механизме расширений — используется метод Выполнить (для процедур) или Вычислить (для функций):

ИмяОбработчика = "МойОбработчикПроверки";

Выполнить(ИмяОбработчика + "(Параметр1, Параметр2)");

У этого подхода есть жёсткие ограничения. Во-первых, Выполнить работает только в контексте текущего модуля — вызвать так метод другого модуля напрямую нельзя, нужна экспортная процедура-прокладка. Во-вторых, параметры подставляются как текст, поэтому строковые значения придётся экранировать кавычками. В-третьих, в безопасном режиме (а дополнительные обработки БСП работают именно в нём) использование Выполнить запрещено.

Вызов серверного обработчика с клиента

Частая задача в управляемых формах: обработчик нажатия кнопки выполняется на клиенте (&НаКлиенте), но логика требует обращения к базе данных, что возможно только на сервере. Решение — разделить обработчик на клиентскую и серверную части:

&НаКлиенте

Процедура КомандаЗаполнить(Команда)

ЗаполнитьНаСервере();

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

&НаСервере

Процедура ЗаполнитьНаСервере()

// Запрос к данным, изменение объекта

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

Серверная процедура вызывается из клиентской просто по имени — платформа сама организует серверный вызов. Учтите ограничения: в серверную процедуру без контекста (&НаСервереБезКонтекста) нельзя передать данные формы напрямую, только примитивные типы и ссылки. Вариант &НаСервере имеет доступ к реквизитам формы, но создаёт более «тяжёлый» вызов с сериализацией данных формы.

Если нужно вызвать клиентский обработчик с задержкой или однократно после завершения текущего действия, используйте ПодключитьОбработчикОжидания("ИмяПроцедуры", 0.1, Истина) — обработчик должен быть экспортной процедурой на клиенте без параметров.

Порядок действий при вызове сервера с клиента
  1. 1
    Создайте клиентский обработчик события с директивой &НаКлиенте
  2. 2
    Добавьте серверную процедуру с директивой &НаСервере или &НаСервереБезКонтекста
  3. 3
    Вызовите серверную процедуру из клиентской по имени, передав только допустимые типы параметров
  4. 4
    Проверьте, что изменённые данные корректно отобразились в форме
  5. 5
    Убедитесь, что нет лишних серверных вызовов в цикле — объединяйте их в один

Вызов обработчиков через подписки на события

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

// Процедура подписки в общем модуле ОбработчикиПодписок

ПодпискаДокументПередЗаписью(ДокументОбъект, Отказ, РежимЗаписи, РежимПроведения);

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

Вызов обработчиков формы извне и обработка оповещений

Для взаимодействия между формами в 1С предусмотрен механизм оповещений. Одна форма вызывает Оповестить("ИмяСобытия", Параметр, Источник), а другая получает это событие в обработчике ОбработкаОповещения(ИмяСобытия, Параметр, Источник). Это штатный способ «вызвать» обработчик в другой форме, не нарушая инкапсуляцию.

Для асинхронных сценариев есть ОписаниеОповещения — объект, содержащий имя экспортной процедуры, которую платформа вызовет после завершения длительной операции (например, после закрытия формы выбора или показа вопроса):

Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияВопроса", ЭтотОбъект);

ПоказатьВопрос(Оповещение, "Продолжить запись?", РежимДиалогаВопрос.ДаНет);

Сравнение способов вызова

Прямой вызов по имени

Самый быстрый и безопасный; требует, чтобы процедура была видна из места вызова и имя было известно при разработке

Выполнить / Вычислить

Подходит для динамических имён из настроек; не работает в безопасном режиме, медленнее, риск инъекции кода

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

Стандарт для обмена между формами; не подходит для вызова внутри одного модуля

ОписаниеОповещения

Для асинхронных вызовов после диалогов и длительных операций; процедура должна быть экспортной

Типичные ошибки и как их избежать

Самая частая ошибка — вызов неэкспортной процедуры из другого модуля. Компилятор выдаст «Процедура или функция с указанным именем не определена». Решение: добавить Экспорт после сигнатуры процедуры, но делайте это осознанно — экспортный интерфейс модуля становится частью его «контракта».

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

Третья типичная проблема — несовпадение параметров. Если обработчик события ожидает (Элемент), а вы вызвали его без параметров, получите ошибку «Недостаточно фактических параметров». При ручном вызове всегда сверяйте сигнатуру в палитре свойств события или в синтакс-помощнике.

Типичные ошибки
01
Вызов неэкспортной процедуры из другого модуля — ошибка компиляции; добавьте Экспорт или перенесите вызов
02
Передача в серверный вызов элементов формы или несериализуемых типов — падение вызова; передавайте ссылки и примитивы
03
Несовпадение числа параметров при ручном вызове обработчика события — ошибка выполнения; сверяйте сигнатуру
04
Использование Выполнить в безопасном режиме — исключение; замените на прямой вызов или заранее заданный список ветвлений
05
Множественные серверные вызовы в цикле — резкое падение производительности формы; объединяйте в один вызов

Как проверить, что обработчик отработал

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

Если обработчик вызывается, но результата нет, проверьте условия внутри него: многие обработчики начинаются с проверок вида Если Отказ Тогда Возврат; или проверки режима обмена данными (Объект.ОбменДанными.Загрузка), которые могут молча прервать выполнение.

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

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

Факт входа в обработчик
Норма

Отладчик останавливается на точке в первой строке процедуры

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

Точка останова не срабатывает — вызов не доходит, проверяйте видимость и директивы

Параметр Отказ после вызова
Норма

Отказ остался Ложь, операция продолжается

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

Отказ = Истина — обработчик отменил операцию, ищите причину в его логике

Изменения данных
Норма

Объект записан, реквизиты формы обновлены

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

Данные не изменились — проверяйте условия выхода и контекст выполнения

FAQ

Можно ли вызвать обработчик события формы из другой формы?

Напрямую — не рекомендуется, формы изолированы. Штатный способ — механизм оповещений: в целевой форме реализуется ОбработкаОповещения, а вызывающая форма выполняет Оповестить() с именем события и параметрами. Альтернатива — получить объект формы через ПолучитьФорму() и вызвать её экспортную процедуру, но это создаёт жёсткую связность.

Почему Выполнить("ИмяПроцедуры()") выдаёт ошибку в дополнительной обработке?

Дополнительные отчёты и обработки БСП исполняются в безопасном режиме, где оператор Выполнить запрещён. Замените динамический вызов на ветвление Если/ИначеЕсли по имени обработчика с прямыми вызовами конкретных процедур.

Как программно «нажать» кнопку на форме?

Вызовите обработчик кнопки напрямую: ИмяПроцедурыНажатия(Элементы.ИмяКнопки) — если обработчик требует параметр Элемент. Если параметров нет, достаточно вызвать процедуру без аргументов. Учтите, что стандартные команды формы (Записать, Провести) лучше вызывать через методы формы: Записать(), а не через имитацию нажатия.

Чем отличается &НаСервере от &НаСервереБезКонтекста при вызове с клиента?

&НаСервере передаёт на сервер всю форму с её реквизитами — вызов медленнее, но внутри доступны данные формы. &НаСервереБезКонтекста передаёт только явно указанные параметры — быстрее и предпочтительнее, но доступа к реквизитам формы внутри процедуры нет.

Можно ли вызвать обработчик ПередЗаписью без реальной записи объекта?

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

Как вызвать обработчик с задержкой или периодически?

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

Итог

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

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