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