Как реализовать отбор в форме выбора по условию «ИЛИ» для нескольких полей

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет Промышленность, строительство и АПК
← На главную

При разработке на платформе 1С:Предприятие 8.3 программисты часто сталкиваются со стандартным поведением системы: при передаче структуры в параметре Отбор функции ОткрытьФорму все условия объединяются по логическому «И». Однако в реальных бизнес-задачах, например, при выборе ресурсных спецификаций в ERP, часто требуется отобразить записи, которые соответствуют либо конкретной номенклатуре, либо определенному виду номенклатуры. Рассмотрим подробнее, как обойти ограничение «И» и реализовать гибкий фильтр.

Метод 1. Использование предварительного запроса и отбора по массиву ссылок

Разберем самый простой и быстрый в реализации способ. Если нам нужно показать записи, подходящие под условие «А» или условие «Б», мы можем сначала выполнить запрос к базе данных, получить список подходящих ссылок и передать их в форму выбора.

Проанализируем ситуацию на примере поиска спецификаций. Сначала создадим функцию на сервере, которая соберет нужные нам данные:


&НаСервереБезКонтекста
Функция ПолучитьСпецификацииПоНоменклатуре(Номенклатура)
    ТекстЗапроса = 
    "ВЫБРАТЬ
    |    РесурсныеСпецификации.Ссылка КАК Ссылка
    |ИЗ
    |    Справочник.РесурсныеСпецификации КАК РесурсныеСпецификации
    |ГДЕ
    |    (РесурсныеСпецификации.ОсновноеИзделиеНоменклатура = &Номенклатура
    |    ИЛИ РесурсныеСпецификации.ОсновноеИзделиеВидНоменклатуры = &ВидНоменклатуры)
    |    И РесурсныеСпецификации.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыСпецификаций.Действует)";

    Запрос = Новый Запрос(ТекстЗапроса);
    Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
    Запрос.УстановитьПараметр("ВидНоменклатуры", Номенклатура.ВидНоменклатуры);
    
    Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
КонецФункции

После того как массив ссылок получен, мы вызываем форму выбора, передавая этот массив в стандартный параметр Отбор. В этом случае система отработает условие «Ссылка В Списке».


&НаКлиенте
Процедура ВыбратьСпецификацию(Команда)
    МассивСсылок = ПолучитьСпецификацииПоНоменклатуре(ТекущаяНоменклатура);
    
    ПараметрыВыбора = Новый Структура;
    ПараметрыВыбора.Вставить("Отбор", Новый Структура("Ссылка", МассивСсылок));
    
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораСпецификации", ЭтаФорма);
    ОткрытьФорму("Справочник.РесурсныеСпецификации.ФормаВыбора", ПараметрыВыбора, ЭтаФорма, , , , ОписаниеОповещения);
КонецПроцедуры

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

Метод 2. Программная настройка Динамического списка в форме выбора

Выясним причину, по которой стандартный отбор нам не подходит: он слишком линеен. Более профессиональный подход заключается в манипуляции настройками компоновки данных (СКД), на которой базируется ДинамическийСписок открываемой формы. Мы можем программно создать группу «ИЛИ».

Рассмотрим алгоритм действий:

  1. Получаем форму выбора, но не открываем ее сразу.
  2. Обращаемся к компоновщику настроек списка.
  3. Добавляем новый элемент отбора типа ГруппаЭлементовОтбораКомпоновкиДанных.
  4. Устанавливаем тип группы в ГруппаИли.
  5. Добавляем условия внутрь этой группы.

Посмотрим на пример реализации этой логики:


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

Этот способ является наиболее производительным, так как платформа сама сформирует оптимальный SQL-запрос с условием WHERE (... OR ...).

Метод 3. Использование инструментов БСП

Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), мы можем упростить код, используя общие модули. В БСП предусмотрены функции для удобной работы с отборами динамических списков.

Проанализируем использование модуля ОбщегоНазначенияКлиентСервер. Хотя стандартная функция УстановитьЭлементОтбораДинамическогоСписка чаще используется для простых отборов, через БСП можно лаконично настраивать параметры открытия формы.

Пример использования структуры фиксированных настроек:


&НаКлиенте
Процедура ОткрытьСИспользованиемБСП()
    Настройки = Новый НастройкиКомпоновкиДанных;
    Отбор = Настройки.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
    Отбор.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли;
    
    // Используем БСП для добавления элементов (упрощенно)
    ОбщегоНазначенияКлиентСервер.ДобавитьЭлементКомпоновки(Отбор, "ОсновноеИзделиеНоменклатура", ВидСравненияКомпоновкиДанных.Равно, Объект.Номенклатура);
    ОбщегоНазначенияКлиентСервер.ДобавитьЭлементКомпоновки(Отбор, "ОсновноеИзделиеВидНоменклатуры", ВидСравненияКомпоновкиДанных.Равно, Объект.ВидНоменклатуры);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ФиксированныеНастройки", Настройки);
    
    ОткрытьФорму("Справочник.РесурсныеСпецификации.ФормаВыбора", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры

Использование параметра ФиксированныеНастройки удобно тем, что эти настройки жестко закрепляются за списком и пользователь не сможет случайно отключить их через меню «Настроить список».

Рекомендации по оптимизации

При реализации сложных отборов в 1С стоит помнить о производительности:

Таким образом, мы разобрали три ключевых подхода к реализации отборов с условием «ИЛИ». Выбор метода зависит от сложности вашей задачи и объема данных в справочнике.

← На главную