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