К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как найти значение в строке в 1С

Как найти значение в строке в 1С: функции СтрНайти и Найти, поиск подстроки, работа с регистром, поиск в таблице значений и запросах. Примеры кода и типичные ошибки.

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

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

Ниже разобраны основные функции и сценарии с примерами кода, условиями выбора и типичными ошибками, которые допускают разработчики при работе со строками в 1С.

Функция СтрНайти — основной способ поиска подстроки

Функция СтрНайти() появилась в платформе 8.3.6 и является рекомендуемым способом поиска подстроки. Она возвращает номер позиции, с которой начинается искомый фрагмент, или 0, если вхождение не найдено. Нумерация символов в 1С начинается с единицы, а не с нуля — это важно учитывать при сравнении с другими языками.

Строка = "Накладная № 12345 от поставщика";

Позиция = СтрНайти(Строка, "12345");

// Позиция = 14

Если СтрНайти(Строка, "поставщик") > 0 Тогда

Сообщить("Подстрока найдена");

КонецЕсли;

Полный синтаксис функции включает дополнительные параметры: СтрНайти(Строка, ПодстрокаПоиска, НаправлениеПоиска, НачальнаяПозиция, НомерВхождения). Направление поиска задаётся значениями НаправлениеПоиска.СНачала или НаправлениеПоиска.СКонца, начальная позиция позволяет искать не с первого символа, а номер вхождения — найти, например, второе или третье вхождение подстроки.

Строка = "а;б;в;а;г";

// Найдём второе вхождение буквы "а"

Позиция = СтрНайти(Строка, "а", НаправлениеПоиска.СНачала, 1, 2);

// Позиция = 7

// Поиск с конца строки

ПозицияСКонца = СтрНайти(Строка, ";", НаправлениеПоиска.СКонца);

// ПозицияСКонца = 8

Функция чувствительна к регистру: поиск «А» и «а» даст разные результаты. Если регистр неважен, перед поиском приведите обе строки к одному регистру функциями ВРег() или НРег().

Устаревшая функция Найти и совместимость

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

Позиция = Найти("ООО Ромашка", "Ромашка"); // Позиция = 5

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

При обновлении конфигураций с режимом совместимости ниже 8.3.6 функция СтрНайти может быть недоступна. Проверьте свойство конфигурации «Режим совместимости» перед использованием новых функций платформы.

Поиск без учёта регистра и с дополнительными условиями

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

Строка = "Счёт-Фактура № 100";

Подстрока = "счёт-фактура";

Если СтрНайти(НРег(Строка), НРег(Подстрока)) > 0 Тогда

Сообщить("Найдено без учёта регистра");

КонецЕсли;

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

Для проверки, начинается ли строка с определённого префикса или заканчивается суффиксом, в платформе есть отдельные функции СтрНачинаетсяС() и СтрЗаканчиваетсяНа(). Они возвращают булево и читаются лучше, чем сравнение позиции с единицей:

Если СтрНачинаетсяС(НомерДокумента, "00-") Тогда

// Обработка номеров с префиксом

КонецЕсли;

При разборе строк с разделителями (CSV, адреса, ФИО) удобнее не искать позиции вручную, а использовать СтрРазделить(Строка, ";", Ложь) — функция вернёт массив частей. Третий параметр Ложь отбрасывает пустые элементы.
ПЗ
Практическое замечание

Поиск значения в данных базы через запрос

Когда искать нужно не в переменной, а в полях справочников или документов, используйте язык запросов. Оператор ПОДОБНО (LIKE) позволяет найти записи, где строковое поле содержит заданный фрагмент:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Наименование КАК Наименование

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Наименование ПОДОБНО &Шаблон";

Запрос.УстановитьПараметр("Шаблон", "%кабель%");

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

Символ процента % означает любую последовательность символов любой длины, подчёркивание _ — ровно один произвольный символ. Шаблон "%кабель%" найдёт «Кабель ВВГ 3х2.5», «Провод-кабель» и любые другие наименования, содержащие это слово.

У оператора ПОДОБНО есть важное ограничение: поиск с шаблоном, начинающимся с %, не использует индексы и при больших объёмах данных выполняется медленно. Для регулярного полнотекстового поиска по наименованиям, описаниям и комментариям правильнее включить полнотекстовый поиск данных в настройках информационной базы.

Поиск значения в таблице значений и табличной части

Таблица значений — не строка, но задача «найти значение» часто относится именно к ней. Для поиска по одной колонке используется метод Найти(Значение, ИмяКолонки), который возвращает первую найденную строку или Неопределено:

СтрокаТовара = ТаблицаТоваров.Найти(ИскомыйАртикул, "Артикул");

Если СтрокаТовара = Неопределено Тогда

Сообщить("Артикул не найден");

Иначе

Сообщить("Количество: " + СтрокаТовара.Количество);

КонецЕсли;

Для поиска по нескольким колонкам или когда нужны все совпадения, используйте НайтиСтроки() со структурой отбора. Метод возвращает массив строк:

Отбор = Новый Структура;

Отбор.Вставить("Склад", СкладОтгрузки);

Отбор.Вставить("Отменено", Ложь);

НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(Отбор);

Для Каждого Строка Из НайденныеСтроки Цикл

// Обработка каждой найденной строки

КонецЦикла;

Методы Найти и НайтиСтроки сравнивают значения по точному совпадению. Поиск по части строки («содержит») через них невозможен — для этого придётся перебирать строки циклом и применять СтрНайти к значению колонки.

Порядок действий при поиске подстроки в колонке таблицы
  1. 1
    Переберите таблицу значений циклом Для Каждого
  2. 2
    Для каждой строки проверьте условие СтрНайти(Строка.Колонка, Подстрока) > 0
  3. 3
    При необходимости приведите оба значения к одному регистру через НРег()
  4. 4
    Соберите подходящие строки в массив или отдельную таблицу
  5. 5
    Проверьте результат: количество найденных строк должно соответствовать ожиданиям на тестовых данных

Проверка результата и границы применения

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

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

Если задача — не программная обработка, а просто найти значение в списке в пользовательском режиме, используйте встроенные средства формы списка: строку поиска (Ctrl+F), отбор по условию «Содержит» или поле полнотекстового поиска в панели навигации, если оно включено администратором.

Типичные ошибки
01
Проверка результата СтрНайти сравнением с -1 вместо 0 — условие всегда истинно, и код ведёт себя непредсказуемо
02
Поиск без учёта регистра с приведением только одной строки — НРег применён к исходной строке, но не к искомой подстроке
03
Использование Найти() в таблице значений для поиска по части строки — метод ищет только точное совпадение
04
Запрос с ПОДОБНО "%текст%" на большой таблице без дополнительных отборов — полное сканирование и замедление работы базы
05
Обращение к найденной строке без проверки на Неопределено — ошибка выполнения при отсутствии значения

Какой способ выбрать в конкретной ситуации

Краткий ориентир: в строковой переменной — СтрНайти, в полях базы данных — запрос с ПОДОБНО или полнотекстовый поиск, в таблице значений — Найти или НайтиСтроки для точного совпадения и цикл со СтрНайти для поиска по вхождению. Выбор между ними определяется тем, где физически находятся данные.

Где находятся данныеИнструментТип поиска
Строковая переменнаяСтрНайтиПодстрока, позиция вхождения
Строковая переменная (префикс/суффикс)СтрНачинаетсяС, СтрЗаканчиваетсяНаПроверка начала и конца строки
Поля справочников и документовЗапрос с ПОДОБНОПо шаблону с % и _
Тексты большого объёма в базеПолнотекстовый поискПо словам с учётом морфологии
Таблица значенийНайти, НайтиСтрокиТочное совпадение значения
Таблица значений (часть строки)Цикл + СтрНайтиВхождение подстроки
Маршрут решения

Как выбрать действие

Нужно найти позицию подстроки в переменнойИспользуйте СтрНайти и проверьте результат на 0
Нужно отобрать записи справочника по части наименованияИспользуйте запрос с ПОДОБНО и параметром-шаблоном
Нужно найти строку в таблице значений по точному значениюИспользуйте Найти() или НайтиСтроки() со структурой отбора
Поиск по подстроке выполняется часто и по большим даннымВключите и настройте полнотекстовый поиск в информационной базе

Часто задаваемые вопросы

Чем СтрНайти отличается от Найти?

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

Как найти подстроку без учёта регистра?

Приведите обе строки к одному регистру перед поиском: СтрНайти(НРег(Строка), НРег(Подстрока)). Позиция вхождения при этом останется корректной, но извлекать фрагмент функцией Сред() нужно из исходной строки.

Почему запрос с ПОДОБНО работает медленно?

Шаблон, начинающийся с символа %, не позволяет использовать индекс, и СУБД сканирует всю таблицу. Добавьте в запрос другие отборы, ограничивающие выборку, или используйте полнотекстовый поиск, который строит специальный индекс по словам.

Как проверить, что в таблице значений ничего не найдено?

Метод Найти() возвращает Неопределено, если совпадений нет — сравнивайте результат с этим значением. Метод НайтиСтроки() возвращает пустой массив, поэтому проверяйте НайденныеСтроки.Количество() = 0.

Можно ли найти все вхождения подстроки в строке?

Да, вызывайте СтрНайти в цикле, передавая начальную позицию после предыдущего найденного вхождения (позиция плюс длина подстроки), пока функция не вернёт 0. Альтернатива — СтрРазделить по искомой подстроке: количество вхождений равно размеру массива минус один.

Как искать значение в списке в режиме пользователя, без программирования?

Откройте форму списка и используйте поиск по Ctrl+F, команду «Найти» в меню «Ещё» или настройку отбора с условием «Содержит». Если администратор включил полнотекстовый поиск, доступна также строка поиска в верхней панели программы.

Итог

Что важно запомнить

В строковых переменных ищите через СтрНайти с проверкой результата на 0, в базе данных — через запрос с ПОДОБНО или полнотекстовый поиск, в таблице значений — через Найти и НайтиСтроки для точного совпадения. Всегда проверяйте результат поиска перед использованием и учитывайте регистр символов.