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

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

При автоматизации загрузки данных из внешних источников (почта, Excel, XML) программисты часто сталкиваются с проблемой дублирования справочников. Типичная ситуация: в базе уже существует группа "Продукты" (с кавычками), а из внешней системы приходит строка Продукты (без кавычек). Стандартный поиск по точному соответствию наименования не находит существующую группу и создает новую. В результате справочник замусоривается дублями, которые отличаются лишь наличием спецсимволов.

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

Проблема стандартного поиска по наименованию

Рассмотрим исходный код, который часто используется для поиска или создания групп. Проблема здесь заключается в жестком условии равенства Номенклатура.Наименование = &Наименование.


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

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

Способ 1: Использование оператора В с перечислением вариантов

Самый простой способ, который подходит для небольших баз и фиксированных правил именования — это передать в запрос массив возможных вариантов написания или использовать логическое "ИЛИ" (через оператор В).

Рассмотрим реализацию этого метода:


// Формируем список возможных наименований
ВариантыНаименований = Новый Массив;
ВариантыНаименований.Добавить(СоздаваемаяПодгруппа); // Без кавычек
ВариантыНаименований.Добавить("""" + СоздаваемаяПодгруппа + """"); // С кавычками

Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.ЭтоГруппа = ИСТИНА
    |	И Номенклатура.Наименование В (&ВариантыНаименований)";

Запрос.УстановитьПараметр("ВариантыНаименований", ВариантыНаименований);

Плюсы: запрос работает быстро, так как СУБД использует индексы по наименованию.

Минусы: метод не учитывает ситуации, когда кавычка стоит только с одной стороны или используются разные типы кавычек (елочки «», лапки „“).

Способ 2: Оператор ПОДОБНО (Маски поиска)

Мы можем использовать оператор ПОДОБНО, чтобы найти группу, в названии которой содержится искомый текст. Однако здесь нужно быть крайне осторожными.


Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.ЭтоГруппа = ИСТИНА
    |	И Номенклатура.Наименование ПОДОБНО &Наименование";

// Поиск по маске: кавычки могут быть в начале и конце
Запрос.УстановитьПараметр("Наименование", "%" + СоздаваемаяПодгруппа + "%");

Важное предостережение: использование символа % в начале строки поиска ("%Текст") отключает использование индексов. База данных будет вынуждена просканировать всю таблицу Справочник.Номенклатура. Если у вас десятки тысяч позиций, это приведет к серьезным тормозам. Кроме того, поиск %Группа% может найти "Группа 1", "Группа 2" и "Подгруппа", что опять же приведет к ошибкам логики.

Способ 3: Функция СТРЗАМЕНИТЬ в запросе (Платформа 8.3.6+)

Современные версии платформы позволяют очищать данные прямо в теле запроса. Это самый гибкий метод. Мы можем "на лету" удалять кавычки из наименований в базе и сравнивать их с "чистым" входящим значением.

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

  1. Программным кодом очищаем входящую строку от всех возможных кавычек.
  2. В запросе используем функцию СТРЗАМЕНИТЬ для очистки поля Наименование.

// Очищаем входящую строку от кавычек
ЧистоеНаименование = СтрЗаменить(СоздаваемаяПодгруппа, """", "");
ЧистоеНаименование = СтрЗаменить(ЧистоеНаименование, "«", "");
ЧистоеНаименование = СтрЗаменить(ЧистоеНаименование, "»", "");

Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.ЭтоГруппа = ИСТИНА
    |	И СТРЗАМЕНИТЬ(Номенклатура.Наименование, """", """") = &Наименование";

Запрос.УстановитьПараметр("Наименование", ЧистоеНаименование);

Обратите внимание на синтаксис СТРЗАМЕНИТЬ(Поле, """", """"). В языке запросов 1С четыре кавычки подряд интерпретируются как одна кавычка (символ "). Таким образом, мы сравниваем "чистые" строки.

Способ 4: Нормализация при записи (Best Practice)

Выясним причину, почему вообще возникает такая сложность. Она кроется в отсутствии единого стандарта именования. Опытные разработчики рекомендуют использовать подход "Нормализованное наименование":

  1. Добавьте в справочник Номенклатура дополнительный реквизит НаименованиеДляПоиска (строка, индексировать).
  2. В событии ПередЗаписью программно заполняйте этот реквизит: переводите в нижний регистр, удаляйте кавычки, лишние пробелы и спецсимволы.
  3. Выполняйте поиск в запросах только по этому реквизиту.

Пример функции нормализации:


Функция НормализоватьСтроку(ВходнаяСтрока)
    Результат = НРег(СокрЛП(ВходнаяСтрока));
    // Удаляем все виды кавычек
    Результат = СтрЗаменить(Результат, """", "");
    Результат = СтрЗаменить(Результат, "«", "");
    Результат = СтрЗаменить(Результат, "»", "");
    // Удаляем неразрывные пробелы
    Результат = СтрЗаменить(Результат, Символы.НПП, " ");
    Возврат Результат;
КонецФункции

Этот метод гарантирует 100% точность сопоставления и высокую скорость работы за счет использования индекса по дополнительному полю.

Резюме и рекомендации

Проанализировав ситуацию, можно сделать следующие выводы:

Помните, что поиск по наименованию всегда несет риски из-за человеческого фактора (опечатки, лишние пробелы). Если есть возможность, всегда старайтесь сопоставлять объекты по уникальным идентификаторам: Код, Артикул или GUID внешней системы.

← На главную