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