Как в 1С 7.7 найти подстроку в строке без учета регистра?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

В платформе 1С:Предприятие 7.7 встроенная функция Найти() является регистрозависимой. Это означает, что при поиске строки "иванов" в тексте "Иванов Иван Иванович" функция вернет 0, так как регистр первых букв не совпадает. В современных версиях платформы (8.х) в запросах эта проблема решается автоматически, но в "семерке" разработчикам приходится применять различные технические уловки. В этой статье мы подробно разберем, как обойти это ограничение, проанализируем производительность разных методов и выберем оптимальные решения для различных ситуаций.

Метод 1: Приведение к единому регистру через НРег() и ВРег()

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

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


// Пример поиска без учета регистра
СтрокаГдеИщем = "Государственный Контракт №123";
ЧтоИщем = "контракт";

Если Найти(НРег(СтрокаГдеИщем), НРег(ЧтоИщем)) > 0 Тогда
    Сообщить("Вхождение найдено!");
КонецЕсли;

Разберем, почему это работает. Функция НРег() (нижний регистр) переводит все буквы в строке в строчные. Таким образом, сравнение происходит между "государственный контракт №123" и "контракт", что позволяет функции Найти() успешно определить позицию вхождения. Аналогично можно использовать функцию ВРег() (верхний регистр).

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

Метод 2: Создание универсальных функций-оберток

Для того чтобы код выглядел чище и его было удобнее поддерживать, рекомендуется вынести логику сравнения в отдельные функции в глобальном модуле или модуле формы. Это позволит вам не задумываться о регистре каждый раз при написании алгоритмов.

Проанализируем пример таких функций:


// Функция для поиска вхождения без учета регистра
Функция НайтиРегНез(Строка1, Строка2)
    Возврат Найти(НРег(Строка1), НРег(Строка2));
КонецФункции

// Функция для точного сравнения строк без учета регистра
Функция СравнитьРегНез(Строка1, Строка2)
    Возврат ?(НРег(Строка1) = НРег(Строка2), 1, 0);
КонецФункции

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

Метод 3: Использование регулярных выражений (VBScript.RegExp)

Если вам необходимо выполнять поиск в больших текстах или использовать сложные условия (например, поиск по маске), лучшим решением будет использование COM-объекта VBScript.RegExp. Этот объект работает на уровне операционной системы и позволяет выполнять поиск без учета регистра гораздо эффективнее, чем стандартные строковые функции 1С 7.7.

Разберем по шагам, как это реализовать:

  1. Создаем объект VBScript.RegExp.
  2. Устанавливаем свойство IgnoreCase в значение 1 (игнорировать регистр).
  3. Передаем искомую строку в свойство Pattern.
  4. Используем метод Test() для проверки наличия или Execute() для получения позиции.

// Пример использования регулярных выражений
RegExp = СоздатьОбъект("VBScript.RegExp");
RegExp.IgnoreCase = 1; // Игнорировать регистр
RegExp.Global = 0;
RegExp.Pattern = "контракт";

ТекстДляПоиска = "Работа с ГосКонтрактами требует внимания.";

Если RegExp.Test(ТекстДляПоиска) = -1 Тогда
    Сообщить("Найдено с помощью RegExp!");
КонецЕсли;

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

Метод 4: Прямые SQL-запросы (для SQL-версий 1С 7.7)

Для баз данных, работающих на MS SQL Server, проблему регистра можно решить на уровне самого сервера. Если вы используете внешние компоненты, такие как 1С++ или Rainbow, вы можете выполнять прямые запросы к таблицам базы данных.

В большинстве случаев базы данных 1С 7.7 создаются с кодировкой (Collation), которая уже настроена как Case Insensitive (CI). Это означает, что оператор LIKE в SQL-запросе найдет данные независимо от того, какими буквами они написаны.

Пример логики запроса:


// Примерный SQL-текст для использования через 1С++
ТекстЗапроса = "
|SELECT * 
|FROM $Справочник.Клиенты as Клиенты
|WHERE Клиенты.Наименование LIKE '%иванов%'
|";

Такой запрос найдет и "Иванов", и "ИВАНОВ", и "иванов". Это самый быстрый способ поиска, если вам нужно отфильтровать список элементов в справочнике или документов по строковому реквизиту.

Метод 5: Полнотекстовый поиск своими силами (Индексация слов)

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

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

Нюансы с буквой "Ё" и национальными раскладками

При реализации поиска без учета регистра в 1С 7.7 программисты часто сталкиваются с проблемой буквы "Ё". Функции НРег() и ВРег() в некоторых сборках платформы могут некорректно обрабатывать эту букву или считать её отличной от "Е".

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


// Пример нормализации строки перед поиском
Стр = СтрЗаменить(НРег(ИсходнаяСтрока), "ё", "е");
Подстрока = СтрЗаменить(НРег(ИскомаяПодстрока), "ё", "е");
Если Найти(Стр, Подстрока) > 0 Тогда
    // Найдено!
КонецЕсли;

Подведем итоги

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

← На главную