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