При разработке пользовательских интерфейсов часто возникает задача организовать поиск или фильтрацию данных сразу по нескольким реквизитам — например, когда введенная пользователем строка должна искаться одновременно в наименовании, коде или артикуле номенклатуры. В такой ситуации требуется наложить фильтр по логическому условию ИЛИ.
Рассмотрим особенности работы со стандартными отборами платформы 1С:Предприятие, проанализируем ограничения обычных форм и разберем по шагам правильные способы реализации такого отбора.
В обычном приложении источником данных табличного поля формы списка справочника является объект СправочникСписок. Коллекция Отбор этого объекта на уровне платформы поддерживает объединение условий исключительно по логическому правилу И (конъюнкция). Если включить отбор по наименованию и отбор по коду, платформа вернет только те элементы, у которых совпали оба поля одновременно.
Создать произвольную группу условий с оператором ИЛИ напрямую в коллекции Список.Отбор для объекта СправочникСписок невозможно. Поэтому стандартный механизм обходят путем предварительной выборки подходящих элементов запросом.
Разберем рабочий алгоритм решения задачи. Чтобы отобразить элементы, подходящие хотя бы под одно из условий, мы сначала выполняем запрос к базе данных, получаем ссылки на найденные объекты, а затем устанавливаем отбор по полю Ссылка с видом сравнения ВидСравнения.ВСписке.
Посмотрим на пример процедуры обработчика изменения строки поиска:
Процедура ПолеВводаСтрокаДляПоискаПриИзменении(Элемент)
СтрокаПоиска = СокрЛП(ПолеВводаСтрокаДляПоиска);
// Если поле поиска очищено, отключаем отбор
Если ПустаяСтрока(СтрокаПоиска) Тогда
Список.Отбор.Ссылка.Использование = Ложь;
Возврат;
КонецЕсли;
// Формируем запрос для поиска по нескольким полям с условием ИЛИ
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| (Номенклатура.Код ПОДОБНО &ШаблонПоиска
| ИЛИ Номенклатура.Артикул ПОДОБНО &ШаблонПоиска
| ИЛИ Номенклатура.Наименование ПОДОБНО &ШаблонПоиска
| ИЛИ Номенклатура.НаименованиеПолное ПОДОБНО &ШаблонПоиска)";
Запрос.УстановитьПараметр("ШаблонПоиска", "%" + СтрокаПоиска + "%");
Выборка = Запрос.Выполнить().Выгрузить();
СписокСсылок = Новый СписокЗначений;
СписокСсылок.ЗагрузитьЗначения(Выборка.ВыгрузитьКолонку("Ссылка"));
// Если ничего не найдено, добавляем пустую ссылку, чтобы очистить список
Если СписокСсылок.Количество() = 0 Тогда
СписокСсылок.Добавить(Справочники.Номенклатура.ПустаяСсылка());
КонецЕсли;
// Важен порядок: сначала меняем ВидСравнения, затем передаем Значение
Список.Отбор.Ссылка.ВидСравнения = ВидСравнения.ВСписке;
Список.Отбор.Ссылка.Значение = СписокСсылок;
Список.Отбор.Ссылка.Использование = Истина;
КонецПроцедуры
Проанализируем ключевые моменты, на которые необходимо обратить внимание при написании кода:
Ссылка гарантирует однозначную идентификацию записей и работает быстрее, чем фильтрация по строковым неиндексированным полям.ВидСравнения = ВидСравнения.ВСписке, и только после этого присваивайте Значение типа СписокЗначений. Если попытаться присвоить список значений при стандартном виде сравнения Равно, платформа вызовет исключение «Неверный тип значения».ПОДОБНО в языке запросов без спецсимволов ищет точное совпадение. Чтобы реализовать поиск по вхождению подстроки, оборачивайте значение в знаки процента: "%" + СтрокаПоиска + "%".СписокЗначений в некоторых версиях платформы может сбросить фильтрацию и отобразить все элементы справочника. Добавление пустой ссылки (Справочники.Номенклатура.ПустаяСсылка()) исключает показ лишних данных.ВЫБРАТЬ ПЕРВЫЕ.Выясним, как аналогичная задача решается в управляемом приложении. Для объекта ДинамическийСписок делать предварительные запросы не требуется, так как система компоновки данных поддерживает группировку условий.
В управляемой форме условие ИЛИ настраивается созданием группы элементов отбора:
&НаКлиенте
Процедура УстановитьОтборИЛИ(СтрокаПоиска)
Список.Отбор.Элементы.Очистить();
Если ПустаяСтрока(СтрокаПоиска) Тогда
Возврат;
КонецЕсли;
// Создаем группу условий ИЛИ
ГруппаИЛИ = Список.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаИЛИ.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИЛИ;
ГруппаИЛИ.Использование = Истина;
// Условие по наименованию
ЭлементОтбора1 = ГруппаИЛИ.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора1.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Наименование");
ЭлементОтбора1.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
ЭлементОтбора1.ПравоеЗначение = СтрокаПоиска;
ЭлементОтбора1.Использование = Истина;
// Условие по коду
ЭлементОтбора2 = ГруппаИЛИ.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора2.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Код");
ЭлементОтбора2.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
ЭлементОтбора2.ПравоеЗначение = СтрокаПоиска;
ЭлементОтбора2.Использование = Истина;
КонецПроцедуры
Таким образом, в обычных формах отбор по условию ИЛИ реализуется через выборку ссылок отдельным запросом и установку вида сравнения ВСписке, а в управляемых формах — через встроенные группы компоновки данных ГруппаИЛИ.