Как найти элемент справочника, если искомое значение хранится в строке с разделителями?

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

Часто в практике разработки на 1С возникает задача поиска элемента справочника, когда несколько значений записаны в одном строковом реквизите через разделитель, например, «123;456;789». Прямой поиск в таком случае затруднен, так как стандартные методы платформы ориентированы на работу с нормализованными данными. Рассмотрим, как решить эту задачу эффективно и корректно.

Почему стандартный поиск не всегда работает?

При использовании оператора ПОДОБНО в запросах 1С, например, при поиске по шаблону "%123%", мы можем получить ложноположительные результаты. Если в справочнике есть значение «1234», поиск найдет его как соответствующее искомому «123». Кроме того, если мы пытаемся перебрать весь справочник в цикле для проверки каждой строки, это приводит к резкому снижению производительности при большом объеме данных. Давайте разберем, как поступить правильно.

Шаг 1: Оптимизация выбора через запрос

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


ВЫБРАТЬ
    Спр.Ссылка,
    Спр.РеквизитСРазделителями
ИЗ
    Справочник.ВашСправочник КАК Спр
ГДЕ
    Спр.РеквизитСРазделителями ПОДОБНО "%" + &ИскомоеЗначение + "%"

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

Шаг 2: Постобработка и точное сравнение

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


Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    МассивЗначений = СтрРазделить(Выборка.РеквизитСРазделителями, ";", Ложь);
    Для Каждого ЭлементМассива Из МассивЗначений Цикл
        Если СокрЛП(ЭлементМассива) = СокрЛП(ИскомоеЗначение) Тогда
            // Мы нашли точный элемент!
            // Теперь можно вернуть ссылку или наименование
            Результат = Выборка.Ссылка;
            Прервать;
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

Шаг 3: Рекомендации по архитектуре данных

Если проект позволяет, мы настоятельно рекомендуем отказаться от хранения списков значений в одной строке. Это считается плохой практикой (нарушение нормализации данных). Лучшими способами решения данной задачи являются:

  1. Табличная часть: Перенесите данные в табличную часть справочника. Тогда поиск превращается в обычный запрос к табличной части, который работает максимально быстро.
  2. Регистр сведений: Создайте независимый регистр сведений, где измерениями будут «ИскомоеЗначение» и «СсылкаНаСправочник». Это обеспечит индексацию и моментальный поиск по любому из этих параметров.

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

← На главную