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