Как получить элемент списка значений по его представлению в 1С?

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

При переходе разработчиков с платформы 1С:Предприятие 7.7 на 1С:Предприятие 8 одной из частых трудностей становится изменение логики работы базовых коллекций данных. Типичный пример такой проблемы — поиск значения в СписокЗначений по его текстовому представлению. Если в «семерке» эта задача решалась буквально в одну строку, то в современных версиях платформы разработчики сталкиваются с определенными ограничениями. В этой статье мы подробно разберем, почему изменилось поведение системы, как правильно организовать поиск по представлению и какие альтернативные структуры данных лучше использовать для решения подобных задач.

Исторический контекст: Разница между 1С 7.7 и 1С 8

Для начала проанализируем, почему этот вопрос вообще возникает. В платформе 1С:Предприятие 7.7 объект СписокЗначений фактически выполнял функции полноценного ассоциативного массива. В нем существовал метод Получить(), который мог принимать в качестве параметра строку представления. Если в метод передавалась строка, система автоматически выполняла внутренний поиск, находила элемент с соответствующим представлением и мгновенно возвращала его значение.

В платформе 1С 8 архитектурный подход к коллекциям был полностью пересмотрен. Метод Получить() теперь принимает только числовой индекс элемента (позицию от 0 до N-1). Прямого платформенного аналога для быстрого поиска по текстовому представлению «из коробки» больше нет. Попытка передать строку в метод Получить() в 1С 8 вызовет ошибку времени выполнения.

Ключевое заблуждение при работе с экранными формами

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


ЭлементыФормы.ПолеВыбора1.СписокВыбора.Добавить("Контрагенты", "Поставщики и покупатели");
ЭлементыФормы.ПолеВыбора1.СписокВыбора.Добавить("Сотрудники", "Сотрудники компании");

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

В 1С 8 элемент управления ПолеВыбора работает по следующему принципу: пользователь интерактивно видит на экране понятное ему Представление («Поставщики и покупатели»), но в связанный реквизит формы автоматически записывается само программное Значение («Контрагенты»). Таким образом, разработчику не нужно вручную сопоставлять выбранный текст со значением — платформа делает это самостоятельно в фоновом режиме. Текст представления попал бы в значение только в том случае, если бы при заполнении списка вы передали одинаковые строки в оба параметра:

СписокВыбора.Добавить("Поставщики и покупатели", "Поставщики и покупатели");

Если же перед вами стоит задача именно программного поиска в произвольном списке значений по текстовому представлению, давайте разберем основные способы ее решения.

Способ 1. Программный обход коллекции в цикле (классический перебор)

Самым очевидным и простым решением в условиях отсутствия штатного метода является обычный перебор элементов списка. Рассмотрим, как это сделать наиболее оптимально.

Для решения этой задачи мы можем применить стандартный цикл Для Каждого. Это наиболее лаконичный и понятный вариант написания кода:


ИскомоеПредставление = "Поставщики и покупатели";
НайденноеЗначение = Неопределено;

Для Каждого ЭлементСписка Из СписокВыбора Цикл
    Если ЭлементСписка.Представление = ИскомоеПредставление Тогда
        НайденноеЗначение = ЭлементСписка.Значение;
        Прервать; // Выходим из цикла сразу, как только нашли нужное соответствие
    КонецЕсли;
КонецЦикла;

Если НайденноеЗначение <> Неопределено Тогда
    // Продолжаем обработку полученного значения
Иначе
    // Обрабатываем ситуацию, когда элемент не найден
КонецЕсли;

В этом примере мы последовательно проверяем свойство Представление каждого элемента коллекции. Как только совпадение найдено, мы сохраняем его Значение в переменную и используем оператор Прервать, чтобы завершить цикл и не тратить процессорное время на обход оставшейся части списка. Это критически важно, если список содержит сотни или тысячи элементов.

Способ 2. Поиск с использованием механизмов БСП

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

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


ПараметрыПоиска = Новый Структура;
ПараметрыПоиска.Вставить("ВариантПоиска", "ПоПредставлению"); 
ПараметрыПоиска.Вставить("ЗначениеПоиска", "Поставщики и покупатели");

НайденныйЭлемент = ОбщийМодульПоиска.НайтиЭлементСпискаЗначений(СписокВыбора, ПараметрыПоиска);

Если НайденныйЭлемент <> Неопределено Тогда
    НужноеЗначение = НайденныйЭлемент.Значение;
КонецЕсли;

Использование функций БСП повышает стандартизацию вашего кода и избавляет от необходимости дублировать однотипные конструкции циклов в разных частях системы.

Способ 3. Альтернативный подход с использованием Соответствия (Map)

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

Объект Соответствие представляет собой классическую хэш-таблицу (набор пар "Ключ" - "Значение"). Поиск элемента по его ключу в такой коллекции реализован платформой на низком уровне и работает практически мгновенно, со сложностью алгоритма близкой к O(1), в то время как поиск перебором в списке значений имеет сложность O(N).

Проанализируем пример работы с коллекцией Соответствие:


// Создаем соответствие и заполняем его данными
ТаблицаСвязей = Новый Соответствие;

// В качестве ключа указываем наше представление (строку), а в качестве значения - нужный объект
ТаблицаСвязей.Вставить("Поставщики и покупатели", "Контрагенты");
ТаблицаСвязей.Вставить("Сотрудники компании", "Сотрудники");

// Теперь мы можем мгновенно получить значение по ключу без всяких циклов
ИскомыйКлюч = "Поставщики и покупатели";
НайденноеЗначение = ТаблицаСвязей.Получить(ИскомыйКлюч);

Если НайденноеЗначение <> Неопределено Тогда
    // Значение успешно получено
Иначе
    // Элемент с таким ключом отсутствует в коллекции
КонецЕсли;

Важное примечание: Почему для этой задачи мы выбираем именно Соответствие, а не похожую на него коллекцию Структура? Дело в ограничениях на имена ключей:

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

Резюме и рекомендации

Разберем по шагам, какой способ решения выбрать в зависимости от вашей конкретной задачи:

  1. Если вы выводите список выбора в форму для интерактивной работы пользователя — используйте стандартный СписокЗначений. Помните, что платформа сама сопоставит представление со значением при выборе, и ручной поиск вам, скорее всего, не понадобится.
  2. Если вам все же необходимо найти элемент по представлению в уже существующем списке значений — используйте лаконичный обход коллекции с помощью цикла Для Каждого с обязательным выходом через Прервать, либо воспользуйтесь функциями БСП.
  3. Если вы проектируете собственный алгоритм в коде, где требуется часто искать данные по текстовому ключу — откажитесь от списка значений в пользу коллекции Соответствие. Это сделает ваш код более производительным и профессиональным.
← На главную