Разработка и Конфигурация · 10 мин
1С: список значений — как найти элемент по представлению
Как в 1С найти элемент списка значений по представлению: перебор, сравнение строк, типичные ошибки и готовые примеры кода для управляемых и обычных форм.
Встроенный метод списка значений НайтиПоЗначению() ищет только по полю «Значение» и не учитывает представление. Если нужно найти элемент именно по представлению — тексту, который видит пользователь, — готового метода в платформе нет, и задачу решают перебором коллекции с сравнением строк. Это частая ситуация при работе с динамически формируемыми списками выбора, отборами и параметрами форм.
Поиск по представлению требуется, когда значение элемента — ссылка, число или служебный идентификатор, а известен только отображаемый текст. Например, список заполнен ссылками на контрагентов, а из внешней системы пришло наименование. Прямой вызов НайтиПоЗначению("ООО Ромашка") вернёт Неопределено, потому что сравнение идёт со ссылкой, а не со строкой.
Ниже разобраны рабочие способы поиска: простой перебор, поиск без учёта регистра, частичное совпадение, а также типичные ошибки — лишние пробелы, незаполненные представления и путаница между значением и представлением.
Что такое представление элемента списка значений
Каждый элемент списка значений имеет четыре свойства: Значение, Представление, Пометка и Картинка. Представление — это строка, которая отображается пользователю в выпадающих списках, диалогах выбора и на формах. Если представление не задано явно при добавлении элемента, платформа формирует его автоматически из строкового представления значения.
Важное следствие: представление может не совпадать со значением. Для элемента со ссылкой на номенклатуру представлением может быть «Товар А (арт. 12345)», а для числового значения — отформатированная строка с разделителями разрядов. Поэтому поиск по представлению всегда сравнивает строки, и к нему применимы все правила строкового сравнения: регистр, пробелы, неразрывные пробелы.
Базовый способ: перебор с точным сравнением
Самый надёжный вариант — пройти по элементам циклом и сравнить свойство Представление с искомой строкой. Функция возвращает найденный элемент или Неопределено, если совпадений нет:
Функция НайтиПоПредставлению(Список, ИскомоеПредставление)
Для Каждого Элемент Из Список Цикл
Если Элемент.Представление = ИскомоеПредставление Тогда
Возврат Элемент;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Вызов выглядит так: НайденныйЭлемент = НайтиПоПредставлению(СписокВыбора, "Основной договор");. Дальше проверяйте результат на Неопределено перед обращением к свойствам элемента — иначе получите ошибку «Поле объекта не обнаружено».
Точное сравнение чувствительно к регистру и пробелам. Строки «Основной договор» и «основной договор » (с пробелом в конце) для оператора = — разные строки. Если данные приходят из внешних источников, почти всегда нужна нормализация.
- 1Убедитесь, что представления в списке заполнены и совпадают с ожидаемым форматом
- 2Напишите функцию перебора с сравнением Элемент.Представление и искомой строки
- 3Добавьте нормализацию: СокрЛП() и при необходимости НРег() к обеим строкам
- 4Проверьте результат на Неопределено перед использованием
- 5Протестируйте на данных с пробелами, разным регистром и дублями представлений
Нормализация строк: регистр и пробелы
Чтобы поиск не зависел от регистра букв, приведите обе строки к одному регистру функцией НРег() или ВРег(). Чтобы убрать ведущие и завершающие пробелы, используйте СокрЛП(). Комбинированный вариант сравнения выглядит так:
Если НРег(СокрЛП(Элемент.Представление)) = НРег(СокрЛП(ИскомоеПредставление)) Тогда
Возврат Элемент;
КонецЕсли;
Отдельная ловушка — неразрывный пробел (символ с кодом 160), который часто попадает в строки при копировании из Excel, веб-страниц или при форматировании чисел. СокрЛП() его не удаляет. Если данные приходят из таких источников, замените его явно: СтрЗаменить(Строка, Символ(160), " "), и только потом применяйте СокрЛП().
Ещё одна тонкость — двойные пробелы внутри строки. Если в представлении «Иванов И.И.» два пробела, а ищут «Иванов И.И.» с одним, точное сравнение не сработает. Для таких случаев либо нормализуйте пробелы заменой « » на « » в цикле, либо переходите к поиску по вхождению подстроки.
Поиск по части представления
Когда точный текст неизвестен, ищут по вхождению подстроки функцией СтрНайти(). Она возвращает позицию вхождения или 0, если подстрока не найдена:
Для Каждого Элемент Из Список Цикл
Если СтрНайти(НРег(Элемент.Представление), НРег(Фрагмент)) > 0 Тогда
// элемент подходит
КонецЕсли;
КонецЦикла;
Поиск по подстроке обычно возвращает несколько элементов, поэтому результат логично собирать в массив или новый список значений, а не возвращать первое совпадение. Это стандартный приём для реализации «живого поиска» по списку при вводе текста пользователем.
Учитывайте производительность: СтрНайти по большому списку при каждом нажатии клавиши может заметно нагружать тонкий клиент. Для списков в тысячи элементов добавляйте задержку обработчика ожидания или ограничивайте поиск минимальной длиной фрагмента в 2–3 символа.
Поиск в списке выбора поля формы
Частный сценарий — список выбора элемента формы, доступный через Элементы.ИмяПоля.СписокВыбора. Это тот же объект СписокЗначений, и приёмы поиска идентичны. Типовая задача: подставить в поле значение, зная только текст, который видит пользователь.
СписокВыбора = Элементы.Договор.СписокВыбора;
Для Каждого Элемент Из СписокВыбора Цикл
Если НРег(СокрЛП(Элемент.Представление)) = НРег(СокрЛП(ТекстПоиска)) Тогда
Объект.Договор = Элемент.Значение;
Прервать;
КонецЕсли;
КонецЦикла;
Обратите внимание: присваивать полю нужно Элемент.Значение, а не представление. Присвоение строки представления в реквизит ссылочного типа приведёт либо к ошибке преобразования типа, либо к молча пустому значению — в зависимости от типа поля.
Дубли представлений и ограничения подхода
Представление не обязано быть уникальным. Два разных контрагента могут иметь одинаковое наименование, и перебор вернёт первый попавшийся элемент — не факт, что нужный. Если дубли возможны, не полагайтесь на представление как на ключ: ищите по значению, а представление используйте только как дополнительный фильтр или для отображения пользователю списка совпадений на выбор.
Второе ограничение — производительность. Перебор — это линейный поиск: на списке из десятков тысяч элементов повторные поиски станут заметны. Если поиск по представлению выполняется часто, постройте один раз соответствие «представление → значение» и дальше ищите по нему за постоянное время:
Индекс = Новый Соответствие;
Для Каждого Элемент Из Список Цикл
Индекс.Вставить(НРег(СокрЛП(Элемент.Представление)), Элемент.Значение);
КонецЦикла;
// далее: НайденноеЗначение = Индекс[НРег(СокрЛП(ТекстПоиска))];
При дублях представлений в соответствии сохранится последнее значение — это тоже нужно учитывать. Если важны все совпадения, храните в соответствии массив значений.
Сравнение вариантов
Подходит для разового поиска по небольшому списку; требует нормализации строк
Для частичного совпадения и живого поиска; возвращает несколько результатов, медленнее на больших списках
Для многократных поисков по одному списку; требует памяти и контроля дублей представлений
Проверка результата и отладка
Если поиск «не находит» заведомо существующий элемент, выведите представления списка в цикле через Сообщить() и сравните с искомой строкой визуально. Часто оказывается, что представление не заполнено, содержит лишние символы или формируется иначе, чем ожидалось — например, с кодом элемента в скобках.
Для диагностики невидимых символов полезно вывести коды символов строки через КодСимвола() — так обнаруживаются неразрывные пробелы и символы табуляции. Проверяйте также, что ищете в актуальном списке: список выбора мог быть перезаполнен после того, как вы сохранили на него ссылку.
Как проверить результат
Возвращён элемент, его Значение и Представление соответствуют ожиданиям
Неопределено при заведомо существующем представлении — проверяйте пробелы и регистр
Вывод в цикле показывает чистый текст без лишних символов
Видны двойные пробелы, коды в скобках, пустые строки
Каждое представление встречается один раз
Дубли — поиск возвращает не тот элемент
Что важно запомнить
Поиска по представлению в списке значений из коробки нет — используйте перебор со сравнением свойства Представление. Нормализуйте строки через СокрЛП(), НРег() и замену неразрывных пробелов. При частых поисках стройте соответствие-индекс, а при дублях представлений ориентируйтесь на значение, а не на текст.
Частые вопросы
Можно ли найти элемент по представлению методом НайтиПоЗначению()?
Нет. Метод сравнивает переданный аргумент со свойством Значение каждого элемента, представление при этом игнорируется. Если значение элемента — ссылка или число, передача строки представления всегда вернёт Неопределено.
Что делать, если представление у элемента пустое?
Если представление не задано явно, при обращении к нему платформа обычно возвращает строковое представление значения, но надёжнее заполнять представление самостоятельно при добавлении элемента: Список.Добавить(Значение, "Нужный текст"). Тогда поиск будет предсказуемым.
Как найти сразу все элементы с подходящим представлением?
В цикле не прерывайтесь на первом совпадении, а добавляйте подходящие элементы в массив или новый список значений. После цикла проверьте количество найденных элементов и обработайте случаи «ничего не найдено» и «найдено несколько» отдельно.
Работает ли этот подход на управляемых формах и в тонком клиенте?
Да, СписокЗначений и его свойства доступны во всех клиентах и на сервере. Ограничение одно: сам объект списка значений нельзя передавать с клиента на сервер в некоторых сценариях, поэтому поиск лучше выполнять там, где список был создан, или передавать данные массивом структур.
Как искать по представлению без учёта регистра?
Приведите обе сравниваемые строки к одному регистру: НРег(СокрЛП(Элемент.Представление)) = НРег(СокрЛП(ИскомаяСтрока)). Этого достаточно для большинства случаев; дополнительно стоит заменить неразрывные пробелы, если данные приходят из Excel или браузера.
Что быстрее — перебор или соответствие?
Для одного-двух поисков разница незаметна, и проще перебор. Если поиск выполняется многократно по одному и тому же списку, однократное построение соответствия «представление → значение» окупается: каждый следующий поиск выполняется практически мгновенно.