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