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