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

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

Как перебрать список значений в 1С

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

Список значений в 1С — это универсальная коллекция, которая хранит набор элементов с представлением, картинкой и пометкой. Её используют для множественного выбора, передачи данных между формами, заполнения табличных частей и отборов в запросах. Чтобы обработать содержимое списка, его нужно перебрать — и встроенный язык предлагает несколько способов сделать это.

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

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

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

Создать и заполнить список можно так:

Список = Новый СписокЗначений;

Список.Добавить(Справочники.Номенклатура.НайтиПоКоду("0001"), "Товар А");

Список.Добавить(Справочники.Номенклатура.НайтиПоКоду("0002"), "Товар Б", Истина);

Третий параметр метода Добавить() задаёт пометку. Дальше рассмотрим, как обойти такой список в разных сценариях.

Базовый перебор циклом «Для Каждого»

Самый читаемый и рекомендуемый способ — итератор Для Каждого ... Из ... Цикл. Он подходит, когда нужно просто обработать все элементы без изменения состава списка:

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

Сообщить(Строка(Элемент.Значение) + " — " + Элемент.Представление);

КонецЦикла;

Внутри цикла доступны все свойства элемента: Элемент.Значение, Элемент.Представление, Элемент.Пометка. Если нужно обработать только отмеченные элементы, добавьте проверку пометки:

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

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

// обработка выбранного значения

КонецЕсли;

КонецЦикла;

Перебор по индексу: прямой и обратный обход

Когда нужен доступ к позиции элемента или требуется модифицировать список во время обхода, применяют классический цикл по индексу. Элементы нумеруются с нуля, поэтому верхняя граница — Количество() - 1:

Для Инд = 0 По Список.Количество() - 1 Цикл

Элемент = Список[Инд];

Сообщить("Позиция " + Инд + ": " + Элемент.Значение);

КонецЦикла;

Для удаления элементов по условию обход выполняют в обратном порядке — тогда удаление не сдвигает индексы ещё не обработанных элементов:

Для Инд = 0 По Список.Количество() - 1 Цикл

ТекИндекс = Список.Количество() - 1 - Инд;

Если Не Список[ТекИндекс].Пометка Тогда

Список.Удалить(ТекИндекс);

КонецЕсли;

КонецЦикла;

Как безопасно удалить элементы при обходе
  1. 1
    Определите условие удаления, например снятая пометка
  2. 2
    Организуйте цикл от 0 до Количество()-1
  3. 3
    Внутри вычислите индекс с конца: Количество()-1-Инд
  4. 4
    Проверьте условие и вызовите Список.Удалить(индекс)
  5. 5
    После цикла проверьте итоговое количество элементов

Поиск элемента без полного перебора

Если задача — найти конкретное значение, полный ручной перебор не нужен: у списка есть метод НайтиПоЗначению(), который возвращает элемент или Неопределено:

Найденный = Список.НайтиПоЗначению(ИскомаяСсылка);

Если Найденный <> Неопределено Тогда

Найденный.Пометка = Истина;

КонецЕсли;

Поиск выполняется по точному равенству значения, включая тип. Строка "001" и число 1 — разные значения, совпадения не будет. Для поиска по представлению метода нет, здесь придётся перебирать список вручную сравнением Элемент.Представление.

Перебор списка на форме и в запросе

Список как реквизит формы

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

Передача списка в запрос

Типичный сценарий — использовать список как отбор в запросе. Перебирать его вручную при этом не нужно: список передаётся параметром целиком, а условие строится через оператор В:

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура

|ГДЕ Ссылка В (&СписокСсылок)";

Запрос.УстановитьПараметр("СписокСсылок", Список);

Результат = Запрос.Выполнить().Выбрать();

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

Преобразование списка в массив и обратно

Иногда удобнее работать с массивом: например, для передачи между клиентом и сервером или для сортировки собственным алгоритмом. Метод ВыгрузитьЗначения() возвращает массив значений, а ЗагрузитьЗначения() заполняет список из массива:

Массив = Список.ВыгрузитьЗначения();

Для Каждого Значение Из Массив Цикл

// работа уже без представлений и пометок

КонецЦикла;

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

Выбор способа перебора

Для Каждого

Чтение всех элементов без изменения списка. Самый короткий и безопасный код

По индексу 0..N-1

Нужна позиция элемента или обращение к соседним элементам

Обратный по индексу

Удаление элементов по условию во время обхода

НайтиПоЗначению

Точечный поиск одного элемента без цикла

ВыгрузитьЗначения

Нужен массив значений для передачи или дальнейшей обработки

Типичные ошибки при переборе списка значений

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

Вторая ошибка — удаление элементов в прямом цикле по индексу. После Список.Удалить(Инд) все последующие элементы сдвигаются на позицию вверх, и один элемент пропускается. Решение — обратный обход.

Третья ошибка — сравнение значений разных типов при поиске. Например, список заполнен ссылками, а ищут строковое представление кода. НайтиПоЗначению() вернёт Неопределено, и логика обработки молча не сработает. Всегда проверяйте типы перед сравнением.

Типичные ошибки
01
Использование переменной цикла как значения вместо Элемент.Значение — ошибка исполнения или неверные данные
02
Удаление элементов в прямом цикле — пропуск части элементов
03
Поиск значения другого типа через НайтиПоЗначению — элемент не находится без явной ошибки
04
Перебор пустого списка без проверки Количество() — лишние ветки кода там, где достаточно одной проверки

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

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

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

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

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

Количество обработанных элементов
Норма

Совпадает с Количество() или числом помеченных

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

Меньше ожидаемого — возможен пропуск при удалении в цикле

Состав списка после обхода
Норма

Удалены только нужные элементы

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

Удалены лишние или остались неудалённые — неверное условие или направление обхода

Результат НайтиПоЗначению
Норма

Возвращён элемент с нужным значением

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

Неопределено при заведомо существующем значении — проверьте тип

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

Как перебрать только помеченные элементы списка?

Используйте цикл «Для Каждого» с проверкой свойства Пометка внутри: «Если Элемент.Пометка Тогда ... КонецЕсли». Отдельного метода фильтрации у списка значений нет.

Как узнать количество элементов в списке значений?

Метод Список.Количество() возвращает число элементов. Перед перебором полезно проверить, что список не пуст: «Если Список.Количество() > 0 Тогда».

Можно ли перебрать список значений на клиенте в управляемой форме?

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

Чем перебор списка значений отличается от перебора массива?

Синтаксис циклов одинаков, но переменная цикла по списку даёт элемент со свойствами Значение, Представление, Пометка, а по массиву — сразу само значение. Перепутав коллекции, легко получить ошибку обращения к свойству.

Как отсортировать список значений перед перебором?

Вызовите Список.СортироватьПоЗначению() или Список.СортироватьПоПредставлению() — после этого перебор пойдёт в отсортированном порядке. Для нестандартного порядка выгрузите значения в массив или таблицу значений и сортируйте там.

Итог

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

Для обычного обхода используйте «Для Каждого» и обращайтесь к Элемент.Значение. Для удаления во время обхода — обратный цикл по индексу. Для точечного поиска — НайтиПоЗначению с учётом типа. Для отбора в запросе список передаётся параметром без перебора.