При доработке типовых конфигураций 1С (например, 1С:Бухгалтерия предприятия 3.0), которые находятся на полной поддержке, разработчики стремятся минимизировать изменения в основной конфигурации. Это позволяет избежать трудностей при последующих обновлениях системы. Идеальным инструментом для решения подобных задач являются расширения конфигурации.
Однако при попытке реализовать подписку на события (например, при записи или проведении документа) внутри расширения программисты часто сталкиваются со следующей проблемой: платформа попросту не дает создать объект типа Подписка на событие в дереве метаданных расширения. Выясним причину этого поведения, разберем ограничения различных версий платформы 1С:Предприятие и детально рассмотрим работающие способы решения данной задачи.
Возможность работы с подписками на события непосредственно внутри расширений конфигурации зависит исключительно от версии используемой вами платформы:
Если вы вынуждены работать на старой версии платформы (например, 8.3.14, как автор вопроса), создавать стандартную подписку в расширении нельзя. В таком случае необходимо использовать альтернативный вариант — перехват событий через модули заимствованных объектов. Ниже мы детально разберем оба сценария.
Если версия вашей платформы не позволяет создать подписку, мы можем использовать механизм аннотаций в модуле объекта заимствованного документа или справочника. Этот метод полностью заменяет подписку на событие для конкретного объекта.
Разберем по шагам, как сделать это правильно, избежав распространенных ошибок синтаксиса:
ОбработкаПроведения или ПередЗаписью).&Перед, &После или &Вместо.Давайте проанализируем разницу между этими аннотациями:
ПродолжитьВызов(), чтобы не прерывать цепочку вызовов других расширений.Посмотрим на пример правильной реализации перехвата события проведения документа с помощью аннотации &После:
&После("ОбработкаПроведения")
Процедура Расш1_ОбработкаПроведения(Отказ, РежимПроведения)
// Переменная "ЭтотОбъект" доступна внутри контекста модуля объекта расширения
НомерДокумента = ЭтотОбъект.Номер;
ДатаДокумента = ЭтотОбъект.Дата;
// Пример вывода сообщения пользователю
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Регистрация проведения документа № " + НомерДокумента + " от " + ДатаДокумента;
Сообщение.Сообщить();
КонецПроцедуры
Важный нюанс: Обратите внимание, что имя процедуры в расширении должно отличаться от оригинального (например, иметь префикс вашего расширения Расш1_ОбработкаПроведения), а список входящих параметров (в данном случае Отказ и РежимПроведения) должен строго и в точности соответствовать оригинальной процедуре в основной конфигурации. Если вы ошибетесь в количестве или названиях параметров, платформа выдаст ошибку времени выполнения. Для выявления подобных проблем в коде можно использовать инструмент для анализа расширений на наличие ошибок в вызовах и сигнатурах.
Давайте разберем, почему у автора вопроса в сообщении №7 не сработал код. Автор попытался написать процедуру следующим образом:
&После("ОбработкаПроведения")
Процедура ОбработкаПроведения_Своя()
...
КонецПроцедуры
Эта процедура не выполнилась по двум ключевым причинам:
ОбработкаПроведения в модуле любого документа 1С всегда принимает два обязательных параметра: Отказ (тип Булево) и РежимПроведения (тип РежимПроведенияДокумента). Автор объявил процедуру без параметров. Платформа не смогла сопоставить вызов и проигнорировала данный обработчик.Если вы обновили платформу до версии 8.3.17 или выше, вам становится доступен полноценный и более элегантный механизм работы с подписками на события. Рассмотрим два сценария использования этого функционала.
Вы можете создать собственную подписку, которая будет реагировать как на объекты из расширения, так и на заимствованные объекты основной конфигурации. Выполните следующие действия:
ПередЗаписью, ПриЗаписи или ОбработкаПроведения).Важный нюанс при работе с обобщенными типами: Если вы хотите настроить подписку сразу на все документы (тип ДокументОбъект) или все справочники (тип СправочникОбъект), платформа имеет интересную особенность. Обобщенный тип отобразится в списке доступных источников только в том случае, если в ваше расширение заимствован хотя бы один документ или справочник из основной конфигурации. После заимствования любого одного документа вы сможете выбрать тип ДокументОбъект целиком, и подписка будет срабатывать для всех документов информационной базы (даже для тех, которые вы не добавляли в расширение).
Этот сценарий необходим, если в основной конфигурации уже есть типовая подписка на события, и вы хотите, чтобы она обрабатывала ваш новый документ или справочник, созданный в расширении.
При этом платформа накладывает жесткое ограничение: в заимствованной подписке разрешается только расширять список источников событий. Вы не можете удалять предопределенные источники или изменять сам обработчик (процедуру общего модуля), назначенный в основной конфигурации.
Проанализируем преимущества и недостатки обоих методов, чтобы вы могли выбрать наиболее архитектурно правильный подход для своего проекта:
| Критерий сравнения | Перехват через модуль объекта (&После, &Перед) | Собственная подписка на событие в расширении |
|---|---|---|
| Поддерживаемые версии платформы | Любые версии (начиная с появления расширений в 8.3.6) | Только платформы версии 8.3.17 и выше |
| Групповая обработка объектов | Неудобно. Приходится заимствовать модуль каждого объекта отдельно и дублировать вызовы. | Удобно. Можно подписаться на обобщенный тип (например, ДокументОбъект) для всей базы. |
| Удобство отладки и чтения кода | Высокое. Разработчик сразу видит перехваченный метод в модуле конкретного объекта. | Среднее. Код обработчика вынесен в отдельный общий модуль, требуется дополнительный поиск связи. |
| Производительность | Высокая. Прямой вызов методов платформой без дополнительных проверок условий. | Высокая, однако при некорректно настроенных обобщенных типах источников может создавать небольшую нагрузку. |
Таким образом, если перед вами стоит задача быстро добавить алгоритм проверки заполнения реквизитов или отправки сообщений для одного-двух конкретных документов — смело используйте заимствование модулей и аннотации &Перед или &После. Если же вы создаете сложную подсистему логирования изменений, которая должна централизованно обрабатывать десятки различных документов и справочников, и ваша платформа обновлена до актуальной версии — создавайте единую подписку на события в расширении.