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