Введение
Наша цель, это оптимизация отчетов на СКД, в которых используется "Набор данных - объект".
Для начала, опишем проблему.
Рассмотрим стандартную схему работы с внешними наборами данных в отчетах на СКД:
В обработчике события отчета "ПриКомпоновкеРезультата":
1) Получаем полные данные
2) Передаем полученные данные в качестве внешних наборов данных в процессор компоновки
3) При формировании отчета отборы пользователя накладываются на изначально излишние данные
То есть обычная ситуация, когда полные данные содержат, скажем, 10000 строк и более, а в результат, с учетом отборов пользователя, попадает лишь малая часть от всех этих данных. Это может вызывать проблемы, если получение исходных данных занимает значительное время.
Пример кода приведенной выше схемы
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получение полных данных, без учета отборов
ТаблицаДанныхОтчета = ТаблицаДанныхОтчета();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
СхемаКомпоновкиДанных,
КомпоновщикНастроек.ПолучитьНастройки(),
ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаДанныхОтчета", ТаблицаДанныхОтчета);
// Применение отборов
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Варианты решения проблемы
1) Анализ настроек компоновки
Мы можем самостоятельно проанализировать настройки компоновки данных и перенести некоторые параметры, и отборы в наш алгоритм получения исходных данных. То есть схема кода будет следующей:
В обработчике события отчета "ПриКомпоновкеРезультата":
1) Анализируем настройки компоновки данных, формируем на их основе собственные параметры для нашего алгоритма
2) Получаем данные с учетом некоторых настроек пользователя
3) Передаем полученные данные в качестве внешних наборов данных в процессор компоновки
4) При формировании отчета отборы пользователя все еще могут сузить изначальный объем полученных данных
Минус данного подхода в том, что мы не сможем учесть все применяемые в отчете настройки пользователя. Механизм СКД предоставляет очень гибкие настройки, а наш алгоритм получения данных для отчета - всегда будет иметь ограниченный набор входящих параметров.
Пример кода приведенной выше схемы
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Анализируем параметры и отборы
ЭлементыОтбора = КомпоновкаДанныхКлиентСервер.ПолучитьЭлементыОтбора(Настройки.Отбор);
МассивНоменклатуры = Новый Массив;
Для каждого ЭлементОтбора Из ЭлементыОтбора Цикл
Если ЭлементОтбора.Использование И ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Номенклатура") Тогда
// Необходимо учесть какой вид сравнения используется
// например это может быть в иерархии, в группе, в списке или просто равенство
// от этого зависит дальнейшая логика применения в нашем алгоритме этого отбора
// В этом примере поддерживаться будет только один вариант
Если ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке Тогда
СписокНоменклатуры = ЭлементОтбора.ПравоеЗначение;
Для каждого ЭлементСписка Из СписокНоменклатуры Цикл
МассивНоменклатуры.Добавить(ЭлементСписка.Значение);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Период = КомпоновкаДанныхКлиентСервер.ПолучитьПараметр(Настройки, "Период");
// Получение полных данных, с учетом некоторых отборов, которые мы смогли учесть
ТаблицаДанныхОтчета = ТаблицаДанныхОтчета(Период, МассивНоменклатуры);
МакетКомпоновки = КомпоновщикМакета.Выполнить(
СхемаКомпоновкиДанных,
Настройки,
ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаДанныхОтчета", ТаблицаДанныхОтчета);
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Посмотрев на код сразу становиться понятно, что анализировать отборы и пытаться их учесть в собственном алгоритме получения данных практически невозможно. Поэтому для текущего подхода лучше всего использовать параметры СКД. Параметры мы явно определяем при разработке схемы и знаем их структуру. Но это лишает нас гибкости и противоречит стандартам (#std407).
2) Использование двух СКД
Если в нашем алгоритме получения данных для отчета мы используем запрос, как это обычно бывает, то можно применить следующую схему:
- Создадим схему компоновки данных, которая будет получать данные. Назовем её "СхемаКомпоновкиЗапрос".
- Создадим схему компоновки данных, которая будет указана в качестве основной схемы отчета. В этой схеме источником будет "Набор данных - объект".
В обработчике события отчета "ПриКомпоновкеРезультата":
- Переносим параметры и отборы из настроек основной схемы компоновки данных в нашу "СхемуКомпоновкиЗапрос".
- Выводим результат "СхемыКомпоновкиЗапрос" в таблицу значений и передаем в качестве внешнего набора данных в основную схему компоновки отчета.
Пример кода приведенной выше схемы
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Инициализируем настройки СхемыКомповнокиДанныхЗапрос
СхемаЗапрос = ПолучитьМакет("СхемаКомпоновкиДанныхЗапрос");
КомпоновщикНастроекСхемыЗапрос = Новый КомпоновщикНастроекКомпоновкиДанных;
ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаЗапрос);
КомпоновщикНастроекСхемыЗапрос.Инициализировать(ИсточникДоступныхНастроек);
КомпоновщикНастроекСхемыЗапрос.ЗагрузитьНастройки(СхемаЗапрос.НастройкиПоУмолчанию);
НастройкиЗапроса = КомпоновщикНастроекСхемыЗапрос.ПолучитьНастройки();
НастройкиОсновнойСхемы = КомпоновщикНастроек.ПолучитьНастройки();
// Перенос настроек (отборов и параметров) основной схемы отчета в настройки схемы-запроса
КомпоновкаДанныхКлиентСервер.СкопироватьОтборКомпоновкиДанных(СхемаЗапрос, НастройкиЗапроса, НастройкиОсновнойСхемы);
КомпоновкаДанныхКлиентСервер.ЗаполнитьЭлементы(НастройкиЗапроса.ПараметрыДанных, НастройкиОсновнойСхемы.ПараметрыДанных);
// Получение внешнего набора данных
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
СхемаЗапрос, НастройкиЗапроса,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ТаблицаДанныхОтчета = Новый ТаблицаЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаДанныхОтчета);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Производим различные манипуляции с ТаблицаДанныхОтчета, преобразуем, дополняем, и т.д.
// Делаем все то, ради чего мы используем объект, а не запрос в основной схеме компоновки отчета
// Формирование отчета
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиОсновнойСхемы, ДанныеРасшифровки);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаДанныхОтчета", ТаблицаДанныхОтчета);
ПроцессорКомпоновки.Инициализировать(ТаблицаДанныхОтчета, ВнешниеНаборыДанных, ДанныеРасшифровки);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Требование, предъявляемое к двум СКД - имена полей и параметров должны совпадать. Ведь именно по ним будет происходит сопоставление и перенос настроек.
Если у вас уже есть готовая СКД с "набором данных - запрос", и вам понадобилось применить метод с двумя СКД, то потребуется вручную описывать поля "набора данных - объект", заново заводить параметры, ресурсы, вычисляемые поля и т.д. К сожалению, как минимум в конфигураторе, возможность копирования между двумя редактируемыми СКД отсутствует. Для облегчения этого процесса к статье приложена обработка которая преобразует СКД с "набором данных - запрос" в СКД с "источником данных - объект", автоматически заполнит типы полей, параметры, ресурсы и т.д.
Итог
Мы рассмотрели метод который позволяет переносить настройки и отборы между двумя различными СКД со схожей структурой. В основном применять его стоит тогда, когда нам необходимо программно обработать таблицу идущую в отчет. Например: распределить остатки на позиции отчета, использовать методы дорабатываемой конфигурации которые предоставляют необходимые данные, что бы не разрабатывать собственный запрос (плюс для долгосрочной поддержки) и т.д.
Ограничения и минусы описанного метода:
- Источником данных может выступать только СКД
- При разработке отчета необходимо следить за соответствием полей в двух СКД
Примеры подобных отчетов из конфигурации ERP 2.5 (2.5.21.104): ОборачиваемостьЗапасов, ТоварныйКалендарь.