Как эффективно найти похожий артикул и предотвратить дублирование номенклатуры в 1С?

Программист 1С v7.7
← На главную

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

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

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

Рассмотрим ситуацию, с которой сталкиваются многие начинающие разработчики. В процедуре ПриЗаписи создается объект справочника и запускается цикл по всем элементам для сравнения артикулов. Проанализируем пример такого кода:


Функция ПохожийАртикул()
    ВыборкаКода = СоздатьОбъект("Справочник.Номенклатура");
    ВыборкаКода.ВыбратьЭлементы();
    Пока ВыборкаКода.ПолучитьЭлемент() = 1 Цикл
        Если ВыборкаКода.Артикул = Артикул Тогда
             // Нашли совпадение
             Возврат ВыборкаКода.ТекущийЭлемент();
        КонецЕсли;
    КонецЦикла;
    Возврат "";
КонецФункции

Почему этот подход плох? Во-первых, при большом количестве записей (десятки и сотни тысяч) такой перебор будет занимать минуты, блокируя работу пользователя. Во-вторых, он ищет только полное совпадение строк. Если в одном случае введен артикул с точкой, а в другом без — проверка не сработает.

Эффективное решение: Использование нормализованного индекса

Для быстрого и качественного поиска мы применим методику «нормализованного поля». Суть заключается в том, чтобы создать в справочнике Номенклатура дополнительный реквизит, например, АртикулПоиск, который будет хранить очищенное значение артикула.

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

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

Шаг 1: Пишем функцию нормализации строки

Выясним причину, по которой обычное сравнение строк не помогает. Это наличие разделителей и разный регистр. Проанализируем функцию, которая «чистит» строку:


Функция глНормализоватьАртикул(Знач Стр) Экспорт
    // Переводим в верхний регистр
    Стр = ВРег(СокрЛП(Стр));
    
    // Удаляем популярные разделители
    Стр = СтрЗаменить(Стр, ".", "");
    Стр = СтрЗаменить(Стр, "-", "");
    Стр = СтрЗаменить(Стр, " ", "");
    Стр = СтрЗаменить(Стр, "/", "");
    Стр = СтрЗаменить(Стр, "\", "");
    
    // Борьба с визуальными дублями (замена кириллицы на латиницу)
    // Это критически важно, так как "С" (рус) и "C" (en) выглядят одинаково
    Стр = СтрЗаменить(Стр, "А", "A");
    Стр = СтрЗаменить(Стр, "В", "B");
    Стр = СтрЗаменить(Стр, "Е", "E");
    Стр = СтрЗаменить(Стр, "К", "K");
    Стр = СтрЗаменить(Стр, "М", "M");
    Стр = СтрЗаменить(Стр, "Н", "H");
    Стр = СтрЗаменить(Стр, "О", "O");
    Стр = СтрЗаменить(Стр, "Р", "P");
    Стр = СтрЗаменить(Стр, "С", "C");
    Стр = СтрЗаменить(Стр, "Т", "T");
    Стр = СтрЗаменить(Стр, "Х", "X");
    
    Возврат Стр;
КонецФункции

Для более продвинутой очистки в современных системах можно использовать объект VBScript.RegExp, но для 1С 7.7 вышеописанный метод является наиболее стабильным и понятным.

Шаг 2: Модернизируем процедуру записи

Теперь внесем изменения в модуль справочника. Рассмотрим, как правильно организовать проверку в процедуре ПриЗаписи. Нам нужно не просто предупредить пользователя, но и не дать записать дубль, если это критично.


Процедура ПриЗаписи()
    // 1. Формируем очищенное значение
    ЧистыйАртикул = глНормализоватьАртикул(Артикул);
    АртикулПоиск = ЧистыйАртикул; // Записываем в скрытый реквизит
    
    // 2. Ищем дубликаты по индексированному полю
    Спр = СоздатьОбъект("Справочник.Номенклатура");
    Если Спр.ВыбратьЭлементыПоРеквизиту("АртикулПоиск", ЧистыйАртикул, 0, 0) = 1 Тогда
        Пока Спр.ПолучитьЭлемент() = 1 Цикл
            // Проверяем, что найденный элемент - не тот же самый, что мы сейчас записываем
            Если Спр.ТекущийЭлемент() <> ТекущийЭлемент() Тогда
                Сообщить("Внимание! Найден дубликат: " + Спр.Наименование + " [" + Спр.Артикул + "]", "!");
                Предупреждение("Товар с таким артикулом уже существует!");
                
                // Если нужно запретить запись, раскомментируйте строку ниже:
                // СтатусВозврата(0); Возврат;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Нюансы производительности и качества данных

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

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

2. Регистронезависимость: Помните, что в файловых версиях 1С 7.7 поиск по индексу обычно регистронезависим, но для SQL-версий это зависит от настроек Collation сервера. Использование ВРег() в коде гарантирует стабильность работы в любой среде.

3. Нечеткий поиск: Если пользователи часто меняют цифры местами (например, вместо 1842 пишут 1824), нормализация не поможет. В таких случаях программисты иногда внедряют алгоритм Расстояния Левенштейна, который вычисляет процент схожести строк. Однако такой поиск нельзя реализовать через стандартный индекс, он требует значительных вычислительных мощностей.

4. Работа с "хвостами": В торговле автозапчастями часто практикуется поиск по последним символам артикула (справа налево). Если ваш бизнес предполагает такую специфику, можно создать еще один поисковый реквизит, куда записывать артикул «задом наперед» или только последние 6 символов.

Резюме

Мы проанализировали проблему дублей и выяснили, что наиболее эффективный метод борьбы с ними в 1С 7.7 — это индексированное поле с нормализованными данными. Использование метода ВыбратьЭлементыПоРеквизиту вместо полного перебора справочника позволяет системе работать мгновенно, а предварительная очистка строки от мусора и замена схожих букв кириллицы/латиницы сводит риск появления дублей к минимуму.

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

← На главную