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

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

1С: список значений — как найти элемент по представлению

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

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

Поиск по представлению требуется, когда значение элемента — ссылка, число или служебный идентификатор, а известен только отображаемый текст. Например, список заполнен ссылками на контрагентов, а из внешней системы пришло наименование. Прямой вызов НайтиПоЗначению("ООО Ромашка") вернёт Неопределено, потому что сравнение идёт со ссылкой, а не со строкой.

Ниже разобраны рабочие способы поиска: простой перебор, поиск без учёта регистра, частичное совпадение, а также типичные ошибки — лишние пробелы, незаполненные представления и путаница между значением и представлением.

Что такое представление элемента списка значений

Каждый элемент списка значений имеет четыре свойства: Значение, Представление, Пометка и Картинка. Представление — это строка, которая отображается пользователю в выпадающих списках, диалогах выбора и на формах. Если представление не задано явно при добавлении элемента, платформа формирует его автоматически из строкового представления значения.

Важное следствие: представление может не совпадать со значением. Для элемента со ссылкой на номенклатуру представлением может быть «Товар А (арт. 12345)», а для числового значения — отформатированная строка с разделителями разрядов. Поэтому поиск по представлению всегда сравнивает строки, и к нему применимы все правила строкового сравнения: регистр, пробелы, неразрывные пробелы.

Базовый способ: перебор с точным сравнением

Самый надёжный вариант — пройти по элементам циклом и сравнить свойство Представление с искомой строкой. Функция возвращает найденный элемент или Неопределено, если совпадений нет:

Функция НайтиПоПредставлению(Список, ИскомоеПредставление)

Для Каждого Элемент Из Список Цикл

Если Элемент.Представление = ИскомоеПредставление Тогда

Возврат Элемент;

КонецЕсли;

КонецЦикла;

Возврат Неопределено;

КонецФункции

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

Точное сравнение чувствительно к регистру и пробелам. Строки «Основной договор» и «основной договор » (с пробелом в конце) для оператора = — разные строки. Если данные приходят из внешних источников, почти всегда нужна нормализация.

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

Нормализация строк: регистр и пробелы

Чтобы поиск не зависел от регистра букв, приведите обе строки к одному регистру функцией НРег() или ВРег(). Чтобы убрать ведущие и завершающие пробелы, используйте СокрЛП(). Комбинированный вариант сравнения выглядит так:

Если НРег(СокрЛП(Элемент.Представление)) = НРег(СокрЛП(ИскомоеПредставление)) Тогда

Возврат Элемент;

КонецЕсли;

Отдельная ловушка — неразрывный пробел (символ с кодом 160), который часто попадает в строки при копировании из Excel, веб-страниц или при форматировании чисел. СокрЛП() его не удаляет. Если данные приходят из таких источников, замените его явно: СтрЗаменить(Строка, Символ(160), " "), и только потом применяйте СокрЛП().

Ещё одна тонкость — двойные пробелы внутри строки. Если в представлении «Иванов И.И.» два пробела, а ищут «Иванов И.И.» с одним, точное сравнение не сработает. Для таких случаев либо нормализуйте пробелы заменой « » на « » в цикле, либо переходите к поиску по вхождению подстроки.

Поиск по части представления

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

Для Каждого Элемент Из Список Цикл

Если СтрНайти(НРег(Элемент.Представление), НРег(Фрагмент)) > 0 Тогда

// элемент подходит

КонецЕсли;

КонецЦикла;

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

Учитывайте производительность: СтрНайти по большому списку при каждом нажатии клавиши может заметно нагружать тонкий клиент. Для списков в тысячи элементов добавляйте задержку обработчика ожидания или ограничивайте поиск минимальной длиной фрагмента в 2–3 символа.

Поиск в списке выбора поля формы

Частный сценарий — список выбора элемента формы, доступный через Элементы.ИмяПоля.СписокВыбора. Это тот же объект СписокЗначений, и приёмы поиска идентичны. Типовая задача: подставить в поле значение, зная только текст, который видит пользователь.

СписокВыбора = Элементы.Договор.СписокВыбора;

Для Каждого Элемент Из СписокВыбора Цикл

Если НРег(СокрЛП(Элемент.Представление)) = НРег(СокрЛП(ТекстПоиска)) Тогда

Объект.Договор = Элемент.Значение;

Прервать;

КонецЕсли;

КонецЦикла;

Обратите внимание: присваивать полю нужно Элемент.Значение, а не представление. Присвоение строки представления в реквизит ссылочного типа приведёт либо к ошибке преобразования типа, либо к молча пустому значению — в зависимости от типа поля.

Типичные ошибки
01
Вызов НайтиПоЗначению() со строкой представления — метод сравнивает со значением элемента и возвращает Неопределено
02
Сравнение без СокрЛП() и НРег() — поиск не находит элементы из-за пробелов и регистра
03
Игнорирование неразрывного пробела (Символ(160)) в данных из Excel и веб-страниц
04
Присвоение полю формы представления вместо значения — ошибка типа или пустой реквизит
05
Отсутствие проверки результата на Неопределено — обращение к свойствам несуществующего элемента

Дубли представлений и ограничения подхода

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

Второе ограничение — производительность. Перебор — это линейный поиск: на списке из десятков тысяч элементов повторные поиски станут заметны. Если поиск по представлению выполняется часто, постройте один раз соответствие «представление → значение» и дальше ищите по нему за постоянное время:

Индекс = Новый Соответствие;

Для Каждого Элемент Из Список Цикл

Индекс.Вставить(НРег(СокрЛП(Элемент.Представление)), Элемент.Значение);

КонецЦикла;

// далее: НайденноеЗначение = Индекс[НРег(СокрЛП(ТекстПоиска))];

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

Сравнение вариантов

Перебор с точным сравнением

Подходит для разового поиска по небольшому списку; требует нормализации строк

Поиск через СтрНайти()

Для частичного совпадения и живого поиска; возвращает несколько результатов, медленнее на больших списках

Соответствие-индекс

Для многократных поисков по одному списку; требует памяти и контроля дублей представлений

Проверка результата и отладка

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

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

Контрольные точки

Как проверить результат

Результат поиска
Норма

Возвращён элемент, его Значение и Представление соответствуют ожиданиям

Тревожный признак

Неопределено при заведомо существующем представлении — проверяйте пробелы и регистр

Содержимое представлений
Норма

Вывод в цикле показывает чистый текст без лишних символов

Тревожный признак

Видны двойные пробелы, коды в скобках, пустые строки

Уникальность
Норма

Каждое представление встречается один раз

Тревожный признак

Дубли — поиск возвращает не тот элемент

Итог

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

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

Частые вопросы

Можно ли найти элемент по представлению методом НайтиПоЗначению()?

Нет. Метод сравнивает переданный аргумент со свойством Значение каждого элемента, представление при этом игнорируется. Если значение элемента — ссылка или число, передача строки представления всегда вернёт Неопределено.

Что делать, если представление у элемента пустое?

Если представление не задано явно, при обращении к нему платформа обычно возвращает строковое представление значения, но надёжнее заполнять представление самостоятельно при добавлении элемента: Список.Добавить(Значение, "Нужный текст"). Тогда поиск будет предсказуемым.

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

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

Работает ли этот подход на управляемых формах и в тонком клиенте?

Да, СписокЗначений и его свойства доступны во всех клиентах и на сервере. Ограничение одно: сам объект списка значений нельзя передавать с клиента на сервер в некоторых сценариях, поэтому поиск лучше выполнять там, где список был создан, или передавать данные массивом структур.

Как искать по представлению без учёта регистра?

Приведите обе сравниваемые строки к одному регистру: НРег(СокрЛП(Элемент.Представление)) = НРег(СокрЛП(ИскомаяСтрока)). Этого достаточно для большинства случаев; дополнительно стоит заменить неразрывные пробелы, если данные приходят из Excel или браузера.

Что быстрее — перебор или соответствие?

Для одного-двух поисков разница незаметна, и проще перебор. Если поиск выполняется многократно по одному и тому же списку, однократное построение соответствия «представление → значение» окупается: каждый следующий поиск выполняется практически мгновенно.