Как в СКД настроить параметры и отборы с необязательным заполнением?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов на базе Системы компоновки данных (СКД) в 1С часто возникает задача сделать так, чтобы параметры или отборы были необязательными для заполнения. Если пользователь не указал конкретное значение (например, оставил пустым поле «Контрагент» или «Склад»), отчет должен формироваться по всем данным без выдачи ошибок и без фильтрации по этому полю. Рассмотрим подробно, как решить эту задачу с помощью встроенного конструктора запросов и программных методов.

Решение 1. Использование расширения языка запросов (фигурные скобки)

Фигурные скобки в СКД представляют собой специальное расширение стандартного языка запросов 1С. С их помощью мы указываем системе компоновки, какие элементы запроса являются динамическими (необязательными). Если пользователь не заполнил параметр, обернутый в фигурные скобки, или отключил его использование на форме, СКД автоматически исключит это условие при генерации итогового SQL-запроса к базе данных.

Рассмотрим подробнее два основных сценария применения фигурных скобок:

  1. Фильтрация в секции ГДЕ:

    Если мы хотим наложить необязательное условие на выборку из реальной таблицы, мы оборачиваем условие в секции ГДЕ в фигурные скобки.

    
    ВЫБРАТЬ
        Продажи.Контрагент КАК Контрагент,
        Продажи.СуммаОборот КАК СуммаОборот
    ИЗ
        РегистрНакопления.Продажи.Обороты КАК Продажи
    {ГДЕ
        (Продажи.Контрагент = &Контрагент)}
    

    Если параметр &Контрагент заполнен, условие применится. Если флаг использования параметра снят или значение пустое, СКД полностью проигнорирует всю конструкцию внутри скобок. Обратите внимание, что для каждого необязательного параметра нужно использовать отдельные фигурные скобки. Объединять разные условия через оператор И внутри одних скобок нельзя.

  2. Фильтрация в параметрах виртуальных таблиц:

    Использование секции ГДЕ заставляет СУБД сначала выбрать все записи, а затем отфильтровать их. Чтобы отчет работал максимально быстро на больших базах данных, фильтрацию необходимо переносить непосредственно в параметры виртуальных таблиц (например, срезов или оборотов). В тексте запроса это выглядит следующим образом:

    
    ВЫБРАТЬ
        ПродажиОбороты.Контрагент КАК Контрагент,
        ПродажиОбороты.СуммаОборот КАК СуммаОборот
    ИЗ
        РегистрНакопления.Продажи.Обороты(,, Авто, {Контрагент.* КАК Контрагент}) КАК ПродажиОбороты
    

    Конструкция {Контрагент.* КАК Контрагент} указывает СКД, что при установке пользователем отбора по контрагенту, СКД автоматически подставит это условие в параметры виртуальной таблицы на уровне базы данных.

Решение 2. Перенос параметров в механизм отборов СКД

Очень часто вместо жестких параметров запроса удобнее использовать стандартный механизм отборов СКД. Отборы по умолчанию являются необязательными: если пользователь не выбрал значение, фильтрация просто не применяется. Для реализации этого подхода выполним следующие шаги:

  1. Уберем явные параметры (например, &Контрагент) из текста запроса в конструкторе.
  2. Перейдем на вкладку Настройки в конструкторе СКД.
  3. Выберем вкладку Отбор в нижней части окна настроек компоновки данных.
  4. Перетащим нужное поле (например, Контрагент) в список отборов.

Выясним причину, почему настроенное поле отбора может не отображаться у пользователя на форме отчета. Чтобы отбор появился в пользовательских настройках на форме, его нужно туда явно включить:

  1. Выделим добавленное поле в списке отборов на вкладке Отбор.
  2. Нажмем на кнопку Свойства элемента пользовательских настроек (она выглядит как шестеренка или кнопка со специальным символом в панели инструментов настроек).
  3. В открывшемся окне установим флаг Включать в пользовательские настройки.
  4. Установим режим отображения (например, Быстрый доступ, чтобы поле выводилось непосредственно на форму отчета).

Важный нюанс: Если после выполнения этих действий поле все равно не появляется на форме в режиме «1С:Предприятие», это может быть связано с кэшированием настроек. Платформа 1С сохраняет пользовательские настройки для каждого отчета. Чтобы принудительно обновить форму, необходимо в режиме предприятия нажать кнопку Еще — Установить стандартные настройки или временно переименовать отчет, чтобы сбросить кэш версии схемы.

Решение 3. Программная настройка параметров и отборов

Проанализируем ситуацию, когда параметры или отборы необходимо заполнять и активировать динамически с помощью кода на встроенном языке. Программную установку параметров обычно выполняют в модуле объекта отчета в предопределенной процедуре ПриКомпоновкеРезультата.

Рассмотрим пример кода для установки и включения параметра в стандартных настройках:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Получаем доступ к параметрам настроек компоновщика
    ПараметрыДанных = КомпоновщикНастроек.Настройки.ПараметрыДанных;
    
    // Ищем требуемый параметр по его имени в СКД
    ПараметрКонтрагент = ПараметрыДанных.Элементы.Найти("Контрагент");
    
    Если ПараметрКонтрагент <> Неопределено Тогда
        Если ЗначениеЗаполнено(ИскомыйКонтрагент) Тогда
            ПараметрКонтрагент.Значение = ИскомыйКонтрагент;
            ПараметрКонтрагент.Использование = Истина; // Включаем фильтрацию
        Иначе
            ПараметрКонтрагент.Использование = Ложь; // Отключаем параметр, делая его необязательным
        КонецЕсли;
    КонецЕсли;

КонецПроцедуры

Однако в современных конфигурациях на платформе 1С v8.3 (Управляемые формы) настройки пользователя имеют приоритет над общими настройками отчета. Если параметр вынесен в пользовательские настройки, изменение КомпоновщикНастроек.Настройки.ПараметрыДанных может не сработать. Чтобы гарантированно переопределить параметр, необходимо работать напрямую с коллекцией пользовательских настроек:


ИдентификаторПараметра = КомпоновщикНастроек.Настройки.ПараметрыДанных.ДоступныеПараметры.Найти("Контрагент").Идентификатор;

Для Каждого Элемент Из КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
    Если ТипЗнч(Элемент) = Тип("ЗначениеПараметраКомпоновкиДанных") 
        И Элемент.Параметр = ИдентификаторПараметра Тогда
        
        Элемент.Значение = ИскомыйКонтрагент;
        Элемент.Использование = ЗначениеЗаполнено(ИскомыйКонтрагент);
        Прервать;
    КонецЕсли;
КонецЦикла;

Свойства параметров: Ограничение доступности и Использование

На вкладке Параметры в схеме компоновки данных (СКД) есть две важные колонки, которые определяют логику поведения полей:

Влияние свойства «Автозаполнение» на доступность отборов

Если при переносе параметров в отборы поле (например, Контрагент) не отображается в списке доступных полей компоновщика, причиной может служить флаг Автозаполнение на вкладке Наборы данных.

Когда автозаполнение включено, СКД самостоятельно анализирует структуру запроса и выводит все обнаруженные поля таблиц в качестве доступных полей отбора. Однако, если поле получается в результате сложных левых соединений, вложенных запросов или объединений таблиц, СКД может не определить однозначную связь поля с физической таблицей базы данных. В таком случае поле пропадает из доступных. Чтобы решить эту проблему, необходимо вручную настроить псевдонимы полей и их связи на вкладках компоновки данных или явно описать доступные поля в фигурных скобках в тексте запроса.

Альтернативный обходной путь (без фигурных скобок)

Иногда при построении сложных динамических запросов использование фигурных скобок может приводить к ошибкам синтаксиса СУБД. В таких ситуациях можно применить классический логический прием непосредственно внутри стандартного условия ГДЕ запроса:


ГДЕ
    (&ИспользоватьФильтрПоКонтрагенту = ЛОЖЬ 
        ИЛИ Таблица.Контрагент = &Контрагент)

В данном случае мы вводим дополнительный булев параметр &ИспользоватьФильтрПоКонтрагенту. В коде перед формированием отчета мы проверяем: если контрагент заполнен, устанавливаем данный вспомогательный параметр в значение Истина, а сам параметр &Контрагент заполняем выбранным значением. Если контрагент не выбран — устанавливаем булев параметр в Ложь. В результате левая часть условия &ИспользоватьФильтрПоКонтрагенту = ЛОЖЬ всегда будет возвращать истину, и СУБД проигнорирует фильтрацию по контрагенту. Стоит учитывать, что данный метод уступает использованию фигурных скобок СКД в плане производительности, так как оптимизатору СУБД сложнее построить оптимальный план выполнения для такого запроса.

← На главную