В типовых конфигурациях 1С, таких как Управление торговлей 11.5 или ERP, стандартный поиск в списках не всегда удовлетворяет запросам пользователей. Часто возникает задача реализовать «умный» поиск: например, чтобы при вводе «вен. ок.» система находила «Вентиляция оконная», игнорируя порядок слов и сокращения. В этой статье мы разберем, как правильно программно управлять отборами динамического списка, почему стандартный оператор ПОДОБНО может не работать и как избежать конфликтов при разработке в расширениях. Для решения этой задачи без самостоятельного написания кода можно использовать расширение для умного поиска в динамических списках и формах выбора.
Рассмотрим ситуацию, с которой сталкиваются многие начинающие разработчики. При попытке соединить несколько слов в одну строку для поиска используется конструкция вида %Слово1%Слово2%. Проанализируем, как это работает на уровне SQL-запроса. Если мы устанавливаем отбор Наименование ПОДОБНО %вен%ок%, система будет искать записи, где сначала встречается фрагмент «вен», а строго после него — фрагмент «ок».
Если в базе данных товар называется «Оконная вентиляция», такой фильтр его не найдет, так как порядок слов нарушен. Именно поэтому поиск по одному слову работает корректно, а при добавлении второго — список становится пустым. Чтобы решить эту проблему, нам нужно изменить логику построения отбора: каждое слово должно проверяться независимо от других. При необходимости можно воспользоваться готовым расширением для поиска объектов по нескольким частям строки независимо от их порядка.
Для реализации поиска по нескольким словам вне зависимости от их позиции, мы должны создать группу элементов отбора с типом И (AND). Каждое слово из поискового запроса станет отдельным элементом внутри этой группы. Разберем по шагам, как это реализовать программно.
Сначала подготовим массив слов, исключив короткие предлоги и лишние пробелы. Затем обратимся к компоновщику настроек динамического списка. Рассмотрим пример кода, который можно разместить в обработчике изменения строки поиска:
&НаКлиенте
Процедура ПоискПриИзменении(Элемент)
СтрокаПоиска = Элемент.ТекстРедактирования;
МассивСлов = СтрРазделить(СтрокаПоиска, " ", Ложь);
// Очищаем предыдущие отборы, чтобы они не суммировались
ГруппаПоиска = Неопределено;
ПолеНаименование = Новый ПолеКомпоновкиДанных("Наименование");
// Ищем существующую группу нашего поиска в настройках
Для Каждого ЭлементОтбора Из Список.КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
Если ТипЗнч(ЭлементОтбора) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных")
И ЭлементОтбора.Представление = "МойПоискПоСловам" Тогда
ГруппаПоиска = ЭлементОтбора;
Прервать;
КонецЕсли;
КонецЦикла;
// Если группы нет — создаем её
Если ГруппаПоиска = Неопределено Тогда
ГруппаПоиска = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
ГруппаПоиска.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИ;
ГруппаПоиска.Представление = "МойПоискПоСловам";
КонецЕсли;
ГруппаПоиска.Элементы.Очистить();
// Добавляем по одному условию ПОДОБНО для каждого значимого слова
Для Каждого Слово Из МассивСлов Цикл
Если СтрДлина(СокрЛП(Слово)) > 1 Тогда
НовыйЭлемент = ГруппаПоиска.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
НовыйЭлемент.ЛевоеЗначение = ПолеНаименование;
НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Подобно;
НовыйЭлемент.ПравоеЗначение = "%" + Слово + "%";
НовыйЭлемент.Использование = Истина;
КонецЕсли;
КонецЦикла;
ГруппаПоиска.Использование = (ГруппаПоиска.Элементы.Количество() > 0);
КонецПроцедуры
При доработке типовых форм через расширения критически важно правильно выбрать аннотацию для обработчика события. Проанализируем ситуацию: если мы используем &После, то сначала выполняется типовой код 1С, который устанавливает свои отборы, а затем — наш код. Часто типовой код может сбрасывать настройки компоновщика или накладывать конфликтующие фильтры.
Если мы используем &Вместо, мы полностью берем управление на себя. Однако в этом случае нужно быть предельно осторожными: если в типовой процедуре выполнялись важные действия (например, обновление связанных итогов или установка параметров запроса), их придется скопировать в расширение, иначе функциональность формы может «сломаться». Выясним причину неработоспособности: часто в УТ 11.5 поиск завязан на программную установку параметров запроса Список.Параметры. Если ваш отбор не дает результата, проверьте, не перебивает ли его стандартный механизм СтрокаПоиска платформы.
Нужно понимать, что использование оператора ПОДОБНО с ведущим процентом (%Слово) лишает СУБД возможности использовать индексы. Это приводит к полному сканированию таблицы (Full Scan). На справочнике в 100 000 позиций это может вызвать заметные задержки.
Помимо настройки фильтров, можно рассмотреть альтернативные варианты ускорения поиска:
Список.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы. Это позволит пользователю видеть, какие фильтры применены, и самостоятельно их отключать.Список.КомпоновщикНастроек.ФиксированныеНастройки. Они имеют наивысший приоритет и не перекрываются пользовательскими фильтрами.В современной платформе 8.3 у динамического списка появилось свойство РежимОбновленияСтрокиПоиска. Проанализируем ситуацию: вместо ручного парсинга строки в коде, мы можем настроить список так, чтобы он автоматически применял стандартные алгоритмы 1С. Однако если стоит задача именно кастомного поиска по «сокращениям» (как в примере «вен. ок.»), программное управление КомпоновщикомНастроек остается единственным гибким инструментом программиста.
Посмотрим на финальный совет: всегда проверяйте, не остаются ли в компоновщике «мусорные» отборы от предыдущих поисковых запросов. Обязательно используйте уникальные представления для своих программных групп отбора, чтобы иметь возможность найти их и удалить перед установкой новых значений.