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