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