Как в динамическом списке установить отбор по двум полям с условием ИЛИ через компоновку данных?

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

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

Проанализируем ситуацию и выясним, как правильно реализовать условие ИЛИ без прямого изменения динамического текста запроса, используя возможности системы компоновки данных.

Использование группы элементов отбора с типом ГруппаИЛИ

Для объединения условий через ИЛИ в компоновке данных предназначен специальный объект — ГруппаЭлементовОтбораКомпоновкиДанных. Разберем по шагам алгоритм создания такого отбора:

  1. Добавляем в коллекцию отбора списка новый элемент с типом ГруппаЭлементовОтбораКомпоновкиДанных.
  2. Указываем тип группы как ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИЛИ.
  3. В коллекцию Элементы созданной группы помещаем обычные элементы с типом ЭлементОтбораКомпоновкиДанных.

Посмотрим на пример программного кода, решающего данную задачу:


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

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

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

Нюансы управления отбором в процессе работы формы

Рассмотрим подробнее важные технические детали, которые необходимо учитывать при программном управлении отборами:

  1. Предотвращение дублирования условий. Если приведенный выше код выполняется повторно (например, в обработчике события ПриИзменении поля выбора склада), каждый вызов будет добавлять новую группу условий. Чтобы избежать загромождения компоновщика, перед созданием группы рекомендуется найти и очистить ранее добавленные элементы. Свойство Представление позволяет легко идентифицировать группу в коллекции Список.Отбор.Элементы.
  2. Сброс настроек пользователем. Элементы, помещенные в Список.Отбор, относятся к пользовательским настройкам формы. Если пользователь выполнит команду стандартных настроек, добавленная группа будет удалена. Если условие должно действовать жестко и постоянно, его следует добавлять в коллекцию Список.ФиксированныеНастройки.Отбор.
  3. Блокировка ручного редактирования. Чтобы пользователь не мог случайно изменить условие в панели настроек списка, используйте свойство РежимОтображения со значением РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный.

Альтернативные варианты реализации

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

  1. Параметризация запроса динамического списка. В тексте запроса можно заранее предусмотреть условие с параметром:
    
    ГДЕ (&ФильтрПоСкладу = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка) 
         ИЛИ СкладПолучатель = &ФильтрПоСкладу 
         ИЛИ СкладОтправитель = &ФильтрПоСкладу)
    
    В этом случае в коде формы достаточно лишь передавать значение через метод Список.Параметры.УстановитьЗначениеПараметра(). Это полностью исключает возню с коллекциями отборов.
  2. Вычисляемое поле в запросе списка. Можно добавить в запрос динамического списка поле через конструкцию ВЫБОР КОГДА СкладПолучатель = &ВыбСклад ИЛИ СкладОтправитель = &ВыбСклад ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦ и накладывать стандартный отбор по этому полю с проверкой на равенство значению Истина.

Влияние условий ИЛИ на производительность

Обратите внимание: наложение условий через логическое ИЛИ по двум разным полям на больших объемах данных может вызывать существенные задержки СУБД. В большинстве случаев СУБД не может применить обычные индексы и выполняет полное сканирование таблицы либо сложное объединение индексов. Для небольших и средних таблиц этот метод полностью безопасен и позволяет быстро получить требуемый результат.

← На главную