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