Как организовать поиск номенклатуры в 1С при произвольном порядке слов в наименовании?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

При активной работе со справочником номенклатуры на складе или в оптово-розничной торговле операторы часто сталкиваются с проблемой: в наименовании товара производитель, модель, тип и характеристики записаны в случайной последовательности. Например, один товар может называться «asus eee pc ноутбук 1225b 4 кг», а другой — «ноутбук 3кг asus eee pc X101CH». В типовых механизмах платформы 1С 7.7 стандартный поиск привязан к жесткой последовательности символов или точному совпадению подстроки, из-за чего найти товар по нескольким ключевым словам становится крайне сложно.

Проанализируем технические и организационные способы решения этой задачи, начиная от создания внешних инструментов поиска и заканчивая оптимизацией структуры справочника.

Особенности работы штатного поиска и специфика задачи

Выясним причину, почему стандартная форма подбора не находит позицию по фрагментам слов. В типовой конфигурации «Торговля и Склад 7.7» поиск в списке справочника выполняется по началу строки либо по точному вхождению одной подстроки. Спецсимволы маскирования (например, знак %) штатным интерфейсом не обрабатываются и воспринимаются как обычные текстовые символы.

Для реализации гибкого поиска необходимо решить ключевую задачу: разбить введенную пользователем поисковую строку на отдельные слова и выполнить выборку элементов, в наименовании которых присутствуют все указанные слова одновременно (логическое условие «И»), независимо от их позиции и расстояния друг от друга.

Решение 1: Поиск на встроенном языке 1С через перебор выборки

Рассмотрим базовый алгоритм, который можно реализовать штатным встроенным языком 1С без использования внешних библиотек и компонентов. Суть метода заключается в разделении поискового шаблона на составляющие части с помощью разделителя (пробела или знака процента) и проверке вхождения каждой части в наименование текущего элемента справочника Справочник.Номенклатура.

Посмотрим на пример реализации алгоритма с последовательным отсечением строк:


тзНоменклатура = СоздатьОбъект("ТаблицаЗначений");
тзНоменклатура.НоваяКолонка("Номенклатура");

СтрШаблон = Врег(СокрЛП(ШаблонПоиска));
сзШаблон = глРазложить(СтрШаблон, " "); // разбиваем строку поиска на отдельные слова

СпрНоменклатура = СоздатьОбъект("Справочник.Номенклатура");
СпрНоменклатура.ВыбратьЭлементы();

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

Такой подход универсален, работает в любых базах (как DBF, так и SQL) и не требует внешних драйверов, однако при объеме справочника свыше нескольких десятков тысяч позиций скорость полного перебора может снижаться.

Решение 2: Формирование динамического запроса 1С с условиями

Разберем еще один штатный вариант, использующий объект Запрос встроенного языка. В этом случае текст запроса динамически конструируется в цикле, добавляя секцию Условие для каждого фрагмента текста.

Посмотрим на программный код построения такого запроса:


Запрос = СоздатьОбъект("Запрос");
РазбиваемаяСтрока = СтрЗаменить(СокрЛП(ПодСтрокаПоиска), " ", РазделительСтрок);

ТекстЗапроса = "
|Без Итогов;
|ТекущийЭлемент = Справочник.Номенклатура.ТекущийЭлемент;
|Наименование = Справочник.Номенклатура.Наименование;
|Группировка ТекущийЭлемент Без Упорядочивания Без Групп;";

Для Индекс = 1 По СтрКоличествоСтрок(РазбиваемаяСтрока) Цикл
    Слово = ВРег(СтрПолучитьСтроку(РазбиваемаяСтрока, Индекс)); 
    Если ПустоеЗначение(Слово) = 1 Тогда
        Продолжить;
    КонецЕсли;    
    ТекстЗапроса = ТекстЗапроса + "
    |Условие(Найти(ВРег(Наименование), """ + Слово + """) > 0);";
КонецЦикла;

Если Запрос.Выполнить(ТекстЗапроса) <> 0 Тогда
    Пока Запрос.Группировка(1) = 1 Цикл
        // Обработка найденных элементов
        НайденныйТовар = Запрос.ТекущийЭлемент;
    КонецЦикла;
КонецЕсли;

Решение 3: Высокоскоростной прямой SQL-запрос (1C++ / 1CSQLite)

Когда требуется мгновенный отклик на базах большого объема, оптимальным решением является использование внешних компонент прямых запросов (например, 1C++ или 1CSQLite). В этом случае запрос отбирает данные на уровне базы через оператор LIKE для каждого слова.

Разберем по шагам построение запроса:


РазбиваемаяСтрока = СтрЗаменить(СокрЛП(стрПоиска), " ", РазделительСтрок);
текст = "SELECT id [Товар :Справочник.Номенклатура] 
        |FROM $Справочник.Номенклатура 
        |WHERE isfolder = 2 AND ismark <> '*'";    

Для Индекс = 1 По СтрКоличествоСтрок(РазбиваемаяСтрока) Цикл
    Слово = СтрПолучитьСтроку(РазбиваемаяСтрока, Индекс); 
    Если ПустоеЗначение(Слово) = 0 Тогда
        текст = текст + " AND (descr LIKE '%" + Слово + "%')";
    КонецЕсли;
КонецЦикла;

тзРезультат = ЗапросSQL.ВыполнитьЗапрос(текст);

Прямой запрос фильтрует записи на уровне ядра СУБД, что обеспечивает результат за доли секунды даже на базах в сотни тысяч строк.

Решение 4: Создание внешней обработки (без изменения конфигурации)

Если у пользователя нет прав на редактирование конфигурации или внесение изменений в типовую структуру запрещено регламентом компании, функционал реализуется через внешнюю обработку (файл с расширением .ert).

  1. Создается отдельная форма внешней обработки с полем ввода поискового запроса и таблицей значений для вывода результатов.
  2. В модуль формы встраивается один из вышеописанных алгоритмов поиска.
  3. При двойном клике по найденной строке в таблице значений вызывается открытие формы элемента или передача выбранного товара в документ (подбор).
  4. Пользователь запускает обработку через главное меню программы «Файл» → «Открыть», не затрагивая конфигурацию.

Решение 5: Пользовательские и организационные методы оптимизации

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

  1. Поиск по уникальному артикулу: Партномер (Part Number) производителя или внутренний артикул уникален. Поиск по точному артикулу исключает влияние порядка слов в описании.
  2. Иерархическая структура каталога: Разделение справочника на логические группы (по типам техники и брендам) позволяет сначала перейти в нужную папку (например, «Ноутбуки / ASUS») и искать уже внутри ограниченного списка.
  3. Единый стандарт заведения номенклатуры: Внедрение регламента формирования наименований (например: [Тип товара] + [Бренд] + [Модель] + [Ключевые параметры]). Соблюдение единого шаблона при вводе новых позиций исключает хаос в наименованиях.
  4. Использование штрихкодирования: При наличии физического товара или заводской упаковки сканирование штрихкода полностью решает проблему ручного поиска.
← На главную