Как в СКД программно установить отбор по списку значений?

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

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

Способ 1. Программное добавление нового элемента отбора

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

Рассмотрим пример формирования списка значений и добавления отбора:


// 1. Формируем список значений для отбора
СписокТоваров = Новый СписокЗначений;
СписокТоваров.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 1"));
СписокТоваров.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 2"));

// 2. Получаем настройки компоновщика
НастройкиКД = КомпоновщикНастроек.Настройки;

// 3. Добавляем новый элемент отбора
НовыйОтбор = НастройкиКД.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйОтбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Номенклатура");
НовыйОтбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
НовыйОтбор.ПравоеЗначение = СписокТоваров;
НовыйОтбор.Использование = Истина;

Разберем основные свойства созданного элемента:

  1. ЛевоеЗначение — путь к полю компоновки данных, по которому выполняется фильтрация. Обязательно создается через объект Новый ПолеКомпоновкиДанных("ИмяПоля").
  2. ВидСравнения — перечисление ВидСравненияКомпоновкиДанных. Для работы со списками используются значения ВСписке, НеВСписке, ВСпискеПоИерархии или НеВСпискеПоИерархии.
  3. ПравоеЗначение — объект типа СписокЗначений или массив с элементами для фильтрации.
  4. Использование — булевый флаг, определяющий активность отбора при компоновке.

Способ 2. Изменение уже существующего отбора

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

Обращение по жесткому индексу (например, Отбор.Элементы[0]) не рекомендуется, так как при изменении структуры настроек порядок элементов может смениться. Безопаснее выполнять поиск по полю:


СписокТоваров = Новый СписокЗначений;
СписокТоваров.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 1"));
СписокТоваров.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Товар 2"));

ПолеПоиска = Новый ПолеКомпоновкиДанных("Номенклатура");
ЭлементНайден = Ложь;

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

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

Особенности работы с пользовательскими настройками

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

Проанализируем, как корректно обновить пользовательский отбор:


ПолеПоиска = Новый ПолеКомпоновкиДанных("Номенклатура");

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

Важные практические нюансы

  1. Защита от дублирования: если вызов процедуры установки отбора происходит в обработчиках формирования отчета или при изменении реквизитов формы, обязательно проверяйте наличие отбора перед вызовом метода Добавить(), иначе при каждом действии пользователя условия будут дублироваться и соединяться логическим «И».
  2. Обработка пустого списка: если в ПравоеЗначение передан пустой СписокЗначений с флагом Использование = Истина, СКД наложит невыполнимое условие (попытается проверить вхождение в пустой набор). В результате отчет вернет пустой результат. Всегда проверяйте СписокТоваров.Количество() > 0 перед включением отбора, а при пустом списке устанавливайте Использование = Ложь.
  3. Иерархический отбор: если переданный список содержит папки (группы) справочника и нужно выбрать не только сами группы, но и всю вложенную номенклатуру, используйте ВидСравненияКомпоновкиДанных.ВСпискеПоИерархии.
  4. Оптимизация производительности: если фильтрация происходит по виртуальным таблицам (например, остаткам или оборотам регистров), стандартный отбор СКД может накладываться после выборки данных. Для ускорения запроса эффективнее передавать список значений через параметры компоновки данных (КомпоновщикНастроек.Настройки.ПараметрыДанных), подставляя его в параметры самой виртуальной таблицы в схеме.
← На главную