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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Способ 1. Перебор массива элементов с использованием функции СтрНайти

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

Разберем реализацию этого алгоритма по шагам:

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

Посмотрим на пример программного кода:


СтрокаШаблонов = "145 R12c,155 R12c,5.00 R12c,155 R13c,145 R13c,155 R13c";
МассивПодстрок = СтрРазделить(СтрокаШаблонов, ",", Ложь);

НаименованиеТовара = Номенклатура.Наименование;
СовпадениеНайдено = Ложь;

Для Каждого Подстрока Из МассивПодстрок Цикл
    ОчищеннаяПодстрока = СокрЛП(Подстрока);
    Если ПустаяСтрока(ОчищеннаяПодстрока) Тогда
        Продолжить;
    КонецЕсли;
    
    Если СтрНайти(НаименованиеТовара, ОчищеннаяПодстрока) > 0 Тогда
        СовпадениеНайдено = Истина;
        Прервать;
    КонецЕсли;
КонецЦикла;

Если СовпадениеНайдено Тогда
    // Выполняем требуемые действия
КонецЕсли;

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

Способ 2. Использование регулярных выражений (RegExp)

Проанализируем ситуацию, когда необходимо проверить совпадение строкового шаблона без предварительного разложения строки на массив. В среде Windows для этого можно использовать объект COMОбъект("VBScript.RegExp"), объединив все искомые подстроки через логический оператор «или» (символ |).

Рассмотрим пример кода:


RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина; // Игнорировать регистр
RegExp.Global = Ложь;

// Формируем паттерн вида: (145 R12c|155 R12c|5\.00 R12c)
// Обратите внимание: спецсимволы регулярных выражений (например, точку) необходимо экранировать
RegExp.Pattern = "(145 R12c|155 R12c|5\.00 R12c|155 R13c|145 R13c)";

Если RegExp.Test(Номенклатура.Наименование) Тогда
    // Подстрока найдена
КонецЕсли;

Ограничения метода:

  1. Платформенная зависимость: вызов COMОбъект работает исключительно в операционных системах Windows. Если сервер 1С работает под управлением Linux, данный код вызовет исключение.
  2. Экранирование метасимволов: знаки ., +, *, (, ), [, ] в регулярных выражениях имеют специальное назначение. Если в подстроках встречаются размеры шин вроде 5.00, точку нужно экранировать обратным слэшем \, иначе она будет означать «любой символ».

Способ 3. Поиск через запрос к базе данных с оператором ПОДОБНО

Если задача заключается в том, чтобы сразу отобрать из базы данных все элементы справочника Номенклатура, удовлетворяющие условиям, можно динамически сформировать текст запроса с условиями ПОДОБНО, объединенными через ИЛИ.

Разберем пример динамического формирования текста запроса:


СтрокаШаблонов = "145 R12c,155 R12c,5.00 R12c,155 R13c,145 R13c";
МассивПодстрок = СтрРазделить(СтрокаШаблонов, ",", Ложь);

Запрос = Новый Запрос;
ТекстУсловий = "";

НомерПараметра = 0;
Для Каждого Подстрока Из МассивПодстрок Цикл
    ОчищеннаяПодстрока = СокрЛП(Подстрока);
    Если ПустаяСтрока(ОчищеннаяПодстрока) Тогда
        Продолжить;
    КонецЕсли;
    
    НомерПараметра = НомерПараметра + 1;
    ИмяПараметра = "Шаблон" + НомерПараметра;
    
    Если ТекстУсловий <> "" Тогда
        ТекстУсловий = ТекстУсловий + " ИЛИ ";
    КонецЕсли;
    
    ТекстУсловий = ТекстУсловий + "Номенклатура.Наименование ПОДОБНО &" + ИмяПараметра;
    Запрос.УстановитьПараметр(ИмяПараметра, "%" + ОчищеннаяПодстрока + "%");
КонецЦикла;

Если НомерПараметра > 0 Тогда
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	Номенклатура.Ссылка КАК Ссылка,
        |	Номенклатура.Наименование КАК Наименование
        |ИЗ
        |	Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |	" + ТекстУсловий;
        
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Обработка найденных элементов
    КонецЦикла;
КонецЕсли;

Подводные камни и риски использования ПОДОБНО в запросах

При использовании запросов с условием ПОДОБНО "%...%" следует учитывать технические особенности работы СУБД:

  1. Отсутствие индексного поиска (Table Scan): использование символа процента % в начале шаблона делает невозможным использование индексов по полю Наименование. СУБД будет выполнять полное сканирование таблицы, что при больших справочниках (от десятков тысяч записей) приведет к существенному падению производительности и блокировкам.
  2. Регистрозависимость в зависимости от СУБД: чувствительность к регистру в операторе ПОДОБНО определяется настройками сортировки (Collation) базы данных. На Microsoft SQL Server поиск, как правило, нечувствителен к регистру, однако на некоторых конфигурациях PostgreSQL сравнение может выполняться с учетом регистра.
  3. Спецсимволы SQL: если в искомой подстроке встречаются знаки %, _ или квадратные скобки, их необходимо экранировать с помощью конструкции СПЕЦСИМВОЛ.

Резюме: для проверки одной конкретной строки в памяти оптимально использовать связку СтрРазделить + СтрНайти с досрочным выходом из цикла через Прервать. Если же требуется масштабная выборка из базы, для ускорения работы рекомендуется использовать механизм полнотекстового поиска (ПолнотекстовыйПоиск.СоздатьСписок), который использует специальные индексы и работает значительно быстрее неиндексированных условий ПОДОБНО.

← На главную