Как реализовать поиск по нескольким словам в динамическом списке 1С

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В типовых конфигурациях 1С, таких как Управление торговлей 11.5 или ERP, стандартный поиск в списках не всегда удовлетворяет запросам пользователей. Часто возникает задача реализовать «умный» поиск: например, чтобы при вводе «вен. ок.» система находила «Вентиляция оконная», игнорируя порядок слов и сокращения. В этой статье мы разберем, как правильно программно управлять отборами динамического списка, почему стандартный оператор ПОДОБНО может не работать и как избежать конфликтов при разработке в расширениях. Для решения этой задачи без самостоятельного написания кода можно использовать расширение для умного поиска в динамических списках и формах выбора.

Разбор типичной ошибки: почему поиск по двум словам не находит данные

Рассмотрим ситуацию, с которой сталкиваются многие начинающие разработчики. При попытке соединить несколько слов в одну строку для поиска используется конструкция вида %Слово1%Слово2%. Проанализируем, как это работает на уровне SQL-запроса. Если мы устанавливаем отбор Наименование ПОДОБНО %вен%ок%, система будет искать записи, где сначала встречается фрагмент «вен», а строго после него — фрагмент «ок».

Если в базе данных товар называется «Оконная вентиляция», такой фильтр его не найдет, так как порядок слов нарушен. Именно поэтому поиск по одному слову работает корректно, а при добавлении второго — список становится пустым. Чтобы решить эту проблему, нам нужно изменить логику построения отбора: каждое слово должно проверяться независимо от других. При необходимости можно воспользоваться готовым расширением для поиска объектов по нескольким частям строки независимо от их порядка.

Эффективный алгоритм: использование групп отбора

Для реализации поиска по нескольким словам вне зависимости от их позиции, мы должны создать группу элементов отбора с типом И (AND). Каждое слово из поискового запроса станет отдельным элементом внутри этой группы. Разберем по шагам, как это реализовать программно.

Сначала подготовим массив слов, исключив короткие предлоги и лишние пробелы. Затем обратимся к компоновщику настроек динамического списка. Рассмотрим пример кода, который можно разместить в обработчике изменения строки поиска:


&НаКлиенте
Процедура ПоискПриИзменении(Элемент)
    
    СтрокаПоиска = Элемент.ТекстРедактирования;
    МассивСлов = СтрРазделить(СтрокаПоиска, " ", Ложь);
    
    // Очищаем предыдущие отборы, чтобы они не суммировались
    ГруппаПоиска = Неопределено;
    ПолеНаименование = Новый ПолеКомпоновкиДанных("Наименование");
    
    // Ищем существующую группу нашего поиска в настройках
    Для Каждого ЭлементОтбора Из Список.КомпоновщикНастроек.Настройки.Отбор.Элементы Цикл
        Если ТипЗнч(ЭлементОтбора) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") 
            И ЭлементОтбора.Представление = "МойПоискПоСловам" Тогда
            ГруппаПоиска = ЭлементОтбора;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    // Если группы нет — создаем её
    Если ГруппаПоиска = Неопределено Тогда
        ГруппаПоиска = Список.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
        ГруппаПоиска.ТипГруппы = ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИ;
        ГруппаПоиска.Представление = "МойПоискПоСловам";
    КонецЕсли;
    
    ГруппаПоиска.Элементы.Очистить();
    
    // Добавляем по одному условию ПОДОБНО для каждого значимого слова
    Для Каждого Слово Из МассивСлов Цикл
        Если СтрДлина(СокрЛП(Слово)) > 1 Тогда
            НовыйЭлемент = ГруппаПоиска.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
            НовыйЭлемент.ЛевоеЗначение = ПолеНаименование;
            НовыйЭлемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Подобно;
            НовыйЭлемент.ПравоеЗначение = "%" + Слово + "%";
            НовыйЭлемент.Использование = Истина;
        КонецЕсли;
    КонецЦикла;
    
    ГруппаПоиска.Использование = (ГруппаПоиска.Элементы.Количество() > 0);

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

Нюансы работы в расширениях: &После или &Вместо?

При доработке типовых форм через расширения критически важно правильно выбрать аннотацию для обработчика события. Проанализируем ситуацию: если мы используем &После, то сначала выполняется типовой код 1С, который устанавливает свои отборы, а затем — наш код. Часто типовой код может сбрасывать настройки компоновщика или накладывать конфликтующие фильтры.

Если мы используем &Вместо, мы полностью берем управление на себя. Однако в этом случае нужно быть предельно осторожными: если в типовой процедуре выполнялись важные действия (например, обновление связанных итогов или установка параметров запроса), их придется скопировать в расширение, иначе функциональность формы может «сломаться». Выясним причину неработоспособности: часто в УТ 11.5 поиск завязан на программную установку параметров запроса Список.Параметры. Если ваш отбор не дает результата, проверьте, не перебивает ли его стандартный механизм СтрокаПоиска платформы.

Оптимизация производительности: почему ПОДОБНО — это медленно

Нужно понимать, что использование оператора ПОДОБНО с ведущим процентом (%Слово) лишает СУБД возможности использовать индексы. Это приводит к полному сканированию таблицы (Full Scan). На справочнике в 100 000 позиций это может вызвать заметные задержки.

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

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

Режим обновления строки поиска

В современной платформе 8.3 у динамического списка появилось свойство РежимОбновленияСтрокиПоиска. Проанализируем ситуацию: вместо ручного парсинга строки в коде, мы можем настроить список так, чтобы он автоматически применял стандартные алгоритмы 1С. Однако если стоит задача именно кастомного поиска по «сокращениям» (как в примере «вен. ок.»), программное управление КомпоновщикомНастроек остается единственным гибким инструментом программиста.

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

← На главную