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