Разработка и Конфигурация · 9 мин
Как найти значение в списке значений 1С
Как найти значение в списке значений 1С: метод НайтиПоЗначению, перебор, сортировка и проверка результата. Примеры кода, ошибки и советы разработчику.
Список значений в 1С — универсальная коллекция, которая встречается почти в каждой конфигурации: отборы в отчётах, параметры запросов, динамические списки, поля с множественным выбором. Рано или поздно возникает задача проверить, есть ли нужное значение в списке, и получить сам элемент. У коллекции есть встроенный метод для этого, но его поведение имеет нюансы, из-за которых поиск иногда «не находит» очевидно существующее значение.
Основной инструмент — метод НайтиПоЗначению(), который возвращает элемент списка или Неопределено, если совпадений нет. Когда встроенного поиска недостаточно — например, нужно искать по представлению или по части строки — применяется перебор коллекции в цикле. Ниже разобраны оба подхода, условия их применения и типичные ошибки.
Что такое список значений и когда в нём ищут
Список значений (тип СписокЗначений) — это упорядоченная коллекция элементов, где каждый элемент хранит четыре свойства: Значение, Представление, Пометка и Картинка. Список может быть типизированным: если задан тип через ТипЗначения, добавить элемент другого типа не получится.
Поиск по списку нужен в типовых сценариях: проверить, выбрал ли пользователь конкретную позицию в отборе отчёта; убедиться, что документ уже добавлен в список обработки и не дублируется; найти элемент, чтобы снять или установить у него пометку; определить индекс значения для последующих операций.
Важно понимать: поиск выполняется по свойству Значение, а не по Представлению. Если в списке лежат ссылки на справочник, а вы ищете строку с наименованием — встроенный метод ничего не найдёт, даже если представление элемента совпадает с вашей строкой.
Метод НайтиПоЗначению: базовый синтаксис
Метод принимает один параметр — искомое значение — и возвращает элемент списка (объект типа ЭлементСпискаЗначений) либо Неопределено. Проверка результата обязательна: обращение к свойствам несуществующего элемента вызовет ошибку.
СписокТоваров = Новый СписокЗначений;
СписокТоваров.Добавить(СсылкаНаТовар, "Товар 1");
НайденныйЭлемент = СписокТоваров.НайтиПоЗначению(СсылкаНаТовар);
Если НайденныйЭлемент <> Неопределено Тогда
Сообщить("Найдено: " + НайденныйЭлемент.Представление);
Сообщить("Индекс: " + СписокТоваров.Индекс(НайденныйЭлемент));
Иначе
Сообщить("Значение в списке отсутствует");
КонецЕсли;
Через найденный элемент доступны все его свойства: можно прочитать или изменить Представление, установить Пометка = Истина, удалить элемент методом Удалить(). Если в списке несколько одинаковых значений, метод вернёт первое из них.
Как работает сравнение значений
Поиск сравнивает и тип, и содержимое значения. Для ссылочных типов (справочники, документы) сравниваются сами ссылки: две ссылки на один и тот же объект базы считаются равными, даже если получены в разные моменты. Для примитивных типов сравнение идёт по значению: число 100 равно числу 100, строка «Аванс» равна строке «Аванс».
Нюансы начинаются на границах типов. Строка «100» не равна числу 100. Дата с временем 10:30:00 не равна той же дате без времени. Булево Истина не равно строке «Истина». Если список типизирован, а искомое значение другого типа, поиск заведомо не найдёт ничего — и это корректное поведение, а не ошибка платформы.
Со строками дополнительно влияют регистр и непечатаемые символы. Сравнение строк в 1С регистронезависимое для оператора равенства, но лишний пробел в конце или неразрывный пробел сделают строки разными. При поиске строковых значений полезно применять СокрЛП() к обеим сторонам сравнения.
Сравните типы через ТипЗнч() и проверьте строки на пробелы
Метод возвращает первое совпадение — проверьте список на дубли
Добавьте ветку Если НайденныйЭлемент <> Неопределено
Поиск перебором: когда встроенного метода мало
Цикл по списку нужен, когда критерий поиска сложнее простого равенства: поиск по представлению, по части строки, по пометке, сбор всех совпадений. Перебор выполняется через Для Каждого ... Из ... Цикл.
// Поиск по представлению с учётом частичного совпадения
Для Каждого Элемент Из СписокЗначений Цикл
Если СтрНайти(ВРег(Элемент.Представление), ВРег(ИскомыйТекст)) > 0 Тогда
Сообщить("Найдено: " + Элемент.Представление);
КонецЕсли;
КонецЦикла;
// Поиск всех элементов с пометкой
Отмеченные = Новый Массив;
Для Каждого Элемент Из СписокЗначений Цикл
Если Элемент.Пометка Тогда
Отмеченные.Добавить(Элемент.Значение);
КонецЕсли;
КонецЦикла;
Перебор медленнее встроенного метода на больших списках, но для типовых объёмов (десятки и сотни элементов) разница незаметна. Если список содержит тысячи элементов и поиск выполняется часто, лучше переформировать логику: например, использовать соответствие (Соответствие), где поиск по ключу работает быстрее, либо свернуть список в таблицу значений с индексом.
Неявный поиск через заполнение и сортировку
Иногда задачу поиска можно решить другими средствами списка. Метод ЗаполнитьЗначения() не ищет, а массово устанавливает значение всем элементам — полезно, когда нужно «сбросить» список. Метод СортироватьПоЗначению() упорядочивает список, что упрощает визуальную проверку и работу пользователя, но на программный поиск не влияет.
Если список пришёл из параметра запроса или отбора СКД, часто достаточно проверить Список.Количество() = 0 и работать со всем списком целиком, не ища конкретное значение. А для проверки вхождения в условии запроса список передаётся в параметр с оператором В (&Список) — тогда поиск выполняет СУБД, что быстрее любого перебора в коде.
Как выбрать действие
Проверка результата и типичные ошибки
Минимальный контроль результата — сравнение с Неопределено до любого обращения к свойствам элемента. Дополнительно полезно проверить индекс найденного элемента через Список.Индекс(Элемент): значение -1 означает, что элемент не принадлежит списку (такое возможно при передаче элемента между разными списками).
Отладка «неудачного» поиска начинается с вывода типов: сравните ТипЗнч(ИскомоеЗначение) с типом значений элементов списка. Второй шаг — вывести значения в цикле и сравнить глазами: часто обнаруживаются лишние пробелы, разные регистры, пустая ссылка вместо заполненной.
Как проверить результат
Элемент списка, доступны Значение и Представление
Неопределено при заведомо существующем значении
ТипЗнч искомого значения совпадает с типом элементов списка
Строка против ссылки, число против строки
Найден ровно тот элемент, который ожидался
Найден дубль или первый элемент вместо нужного
FAQ
Чем НайтиПоЗначению отличается от метода Индекс()?
НайтиПоЗначению ищет по значению и возвращает элемент списка. Индекс() работает наоборот: принимает элемент списка и возвращает его позицию (число от 0) или -1, если элемент не принадлежит списку. Методы дополняют друг друга: сначала находите элемент, затем при необходимости узнаёте его позицию.
Как проверить, есть ли значение в списке, одной строкой?
Используйте выражение Список.НайтиПоЗначению(Значение) <> Неопределено — оно вернёт Истина при наличии значения. Такую проверку удобно вставлять прямо в условие Если без промежуточной переменной.
Почему поиск не находит ссылку, которая точно есть в списке?
Чаще всего дело в несовпадении типов: в списке ссылка одного вида справочника, а ищется другого, либо передаётся уникальный идентификатор или строка вместо ссылки. Реже встречается ситуация с «битой» ссылкой. Выведите ТипЗнч() для искомого значения и для элементов списка — расхождение станет видно сразу.
Как найти элемент списка по представлению?
Встроенного метода нет — НайтиПоЗначению смотрит только на свойство Значение. Переберите список циклом и сравнивайте Элемент.Представление с искомой строкой, при необходимости через ВРег() и СокрЛП() для устойчивого сравнения.
Что быстрее: поиск в списке значений или в соответствии?
Для частого поиска на больших объёмах соответствие быстрее, так как поиск по ключу не требует перебора. Список значений удобнее, когда нужны представление, пометка и показ пользователю. Выбор зависит от задачи: для интерфейсных отборов — список, для служебных проверок вхождения — соответствие.
Можно ли найти значение в списке на стороне запроса?
Да. Передайте список в параметр запроса и используйте условие ГДЕ Поле В (&Список). Проверку вхождения выполнит СУБД, что особенно эффективно при фильтрации больших выборок. Обратный вариант — НЕ В (&Список) — отберёт записи, которых в списке нет.
Что важно запомнить
Для точного поиска используйте НайтиПоЗначению() и всегда проверяйте результат на Неопределено. Метод сравнивает тип и значение, возвращает только первое совпадение и игнорирует представление. Для поиска по представлению, части строки или сбора всех совпадений применяйте перебор в цикле, а для проверок внутри запроса — оператор В (&Список).