Как передать несколько значений в параметр динамического списка для реализации сложного отбора?

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

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

Метод 1: Использование массива в параметрах запроса

Основная сложность заключается в том, что параметр запроса обычно воспринимает одно значение. Чтобы передать список значений (несколько групп), мы должны использовать коллекцию Массив и специальный оператор в тексте запроса динамического списка.

Разберем по шагам, как это реализовать. Сначала нам необходимо подготовить сам запрос динамического списка. В поле Настройка списка — Запрос мы должны прописать условие с использованием оператора В. Проанализируем пример кода запроса:


ВЫБРАТЬ
    СправочникТовары.Ссылка КАК Ссылка,
    СправочникТовары.Наименование КАК Наименование,
    СправочникТовары.Артикул КАК Артикул
ИЗ
    Справочник.Товары КАК СправочникТовары
ГДЕ
    СправочникТовары.Родитель В (&Группы)

Здесь параметр &Группы будет принимать наш массив ссылок. Теперь рассмотрим программный код на встроенном языке 1С, который будет формировать этот массив и передавать его в список при изменении флажков на форме.


&НаСервере
Процедура ОбновитьОтборНаСервере()

    СписокГрупп = Новый Массив;

    // Проверяем состояние каждого флажка на форме
    Если Группа1 Тогда
        СписокГрупп.Добавить(Справочники.ГруппыТоваров.НайтиПоНаименованию("Группа 1"));
    КонецЕсли;

    Если Группа2 Тогда
        СписокГрупп.Добавить(Справочники.ГруппыТоваров.НайтиПоНаименованию("Группа 2"));
    КонецЕсли;

    Если Группа3 Тогда
        СписокГрупп.Добавить(Справочники.ГруппыТоваров.НайтиПоНаименованию("Группа 3"));
    КонецЕсли;

    Если Группа4 Тогда
        СписокГрупп.Добавить(Справочники.ГруппыТоваров.НайтиПоНаименованию("Группа 4"));
    КонецЕсли;

    // Устанавливаем массив как значение параметра
    Список.Параметры.УстановитьЗначениеПараметра("Группы", СписокГрупп);

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

Важный нюанс: использование метода НайтиПоНаименованию считается плохой практикой в профессиональной разработке, так как при переименовании группы в пользовательском режиме код перестанет работать. Рассмотрим более надежный вариант: если группы предопределены, используйте Справочники.ГруппыТоваров.ИмяГруппы. Если нет — лучше хранить ссылки в реквизитах формы или константах.

Метод 2: Решение проблемы «пустого списка»

При использовании первого метода мы столкнемся с проблемой: если пользователь снимет все галочки, массив СписокГрупп будет пустым. В этом случае запрос Родитель В (&Группы) вернет пустой результат (ни одного товара), хотя логично было бы показать все товары, когда фильтры не выбраны.

Проанализируем, как обойти это ограничение. Мы добавим в запрос дополнительный параметр-флаг &ОграничиватьПоГруппам. Посмотрим на обновленный текст запроса:


ВЫБРАТЬ * ИЗ Справочник.Товары ГДЕ (НЕ &ОграничиватьПоГруппам ИЛИ Родитель В (&Группы))

Теперь подправим программный код для обработки этой логики:


&НаСервере
Процедура ОбновитьОтборСПроверкойНаСервере()

    СписокГрупп = Новый Массив;
    // ... заполнение массива (см. выше) ...

    ОграничениеАктивно = (СписокГрупп.Количество() > 0);
    
    Список.Параметры.УстановитьЗначениеПараметра("Группы", СписокГрупп);
    Список.Параметры.УстановитьЗначениеПараметра("ОграничиватьПоГруппам", ОграничениеАктивно);

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

Метод 3: Использование отборов компоновщика настроек

Иногда изменение текста запроса нежелательно или невозможно. В таких случаях мы можем использовать Компоновщик настроек динамического списка. Этот способ считается более «правильным» с точки зрения архитектуры 1С, так как система сама оптимизирует запрос под капотом.

Рассмотрим, как реализовать программную установку отбора типа «В списке»:


&НаСервере
Процедура УстановитьОтборЧерезКомпоновщик()

    СписокГрупп = Новый Массив;
    // ... заполняем массив ссылками на группы ...

    // Ищем существующий элемент отбора по полю "Родитель"
    ПолеОтбора = Новый ПолеКомпоновкиДанных("Родитель");
    ЭлементОтбора = Неопределено;

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

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

    // Настраиваем параметры отбора
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
    ЭлементОтбора.ПравоеЗначение = СписокГрупп;
    ЭлементОтбора.Использование = (СписокГрупп.Количество() > 0);
    ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;

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

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

Оптимизация производительности и обновление списка

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

  1. Для каждого реквизита флажка на форме в палитре свойств создайте событие ПриИзменении.
  2. Внутри обработчика вызывайте процедуру обновления (обязательно с серверным контекстом).
  3. Если после установки параметров динамический список не обновился визуально, принудительно вызовите метод Элементы.Список.Обновить(); на клиенте.

Разберем пример клиентского кода:


&НаКлиенте
Процедура Группа1ПриИзменении(Элемент)
    ОбновитьОтборНаСервере();
    // Обычно список обновляется сам при изменении параметров,
    // но в сложных случаях можно добавить:
    // Элементы.Список.Обновить();
КонецПроцедуры

Подведем итог: для передачи нескольких значений (Группа 1 + Группа 3) наиболее эффективным является использование Массива в сочетании с оператором В в запросе или использование Компоновщика настроек с видом сравнения В списке. Выбор конкретного метода зависит от сложности иерархии ваших справочников и требований к гибкости отбора.

← На главную