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

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

Как перебрать строки динамического списка в 1С

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

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

Понимание этого принципа экономит часы отладки. Многие разработчики пытаются обратиться к данным списка напрямую, получают ошибку или пустой результат и делают неверный вывод, что «список пустой». На самом деле данные есть — просто платформа не отдаёт их в виде коллекции. Ниже разобраны рабочие способы обхода: от простого повторного запроса до полноценного программного выполнения СКД с учётом отборов, установленных пользователем.

Почему динамический список нельзя перебрать напрямую

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

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

Способ 1. Обработка выделенных строк списка

Самый частый сценарий на практике — обработать строки, которые пользователь выделил мышью или через Ctrl+A. Для этого используется коллекция ВыделенныеСтроки элемента формы «Таблица», отображающего список. Каждый элемент коллекции — идентификатор строки: для списка справочника или документов это ссылка, для регистра сведений — ключ записи.

Для Каждого КлючСтроки Из Элементы.Список.ВыделенныеСтроки Цикл

// Для списка документов КлючСтроки — это ссылка на документ

ДокументОбъект = КлючСтроки.ПолучитьОбъект();

ДокументОбъект.Проведен = Истина;

ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);

КонецЦикла;

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

Порядок действий для выделенных строк
  1. 1
    Убедитесь, что у таблицы формы включён множественный выбор (РежимВыделения — Множественный)
  2. 2
    Получите массив Элементы.Список.ВыделенныеСтроки
  3. 3
    Проверьте, что массив не пуст
  4. 4
    В цикле преобразуйте ключ строки в объект и выполните обработку
  5. 5
    После цикла вызовите Элементы.Список.Обновить() для обновления отображения

Способ 2. Повторный запрос к базе с теми же отборами

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

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

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

Запрос.Текст = Список.ТекстЗапроса;

Запрос.УстановитьПараметр("Организация", ТекущаяОрганизация);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

// Обработка каждой строки выборки

КонецЦикла;

Способ 3. Программное выполнение СКД списка

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

СхемаКомпоновки = Новый СхемаКомпоновкиДанных;

Источник = СхемаКомпоновки.ИсточникиДанных.Добавить();

Источник.Имя = "ИсточникДанных1";

Источник.ТипИсточникаДанных = "Local";

Набор = СхемаКомпоновки.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));

Набор.Запрос = Список.ТекстЗапроса;

Набор.Имя = "НаборДанных1";

Набор.ИсточникДанных = "ИсточникДанных1";

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

Настройки = Список.КомпоновщикНастроек.ПолучитьНастройки();

Макет = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

Процессор = Новый ПроцессорКомпоновкиДанных;

Процессор.Инициализировать(Макет);

Результат = Новый ТаблицаЗначений;

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;

ПроцессорВывода.УстановитьОбъект(Результат);

ПроцессорВывода.Вывести(Процессор);

Для Каждого СтрокаРезультата Из Результат Цикл

// Обход строк таблицы значений

КонецЦикла;

Для корректной работы в схеме нужно добавить поля набора данных (достаточно перечислить используемые поля запроса) и задать в настройках структуру — хотя бы группировку «Детальные записи» с выбранными полями, иначе результат будет пустым. Если в запросе списка есть параметры, их значения передаются через коллекцию Настройки.ПараметрыДанных.

Способ 4. Получение данных через временную таблицу формы

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

Цена решения — потеря «динамичности»: автоматического обновления, порционной загрузки и стандартных команд списка (создать, скопировать, изменить) не будет, их придётся реализовывать вручную. Для больших таблиц добавится и расход памяти на клиенте, так как таблица значений загружается целиком.

Сравнение способов обхода данных списка

ВыделенныеСтроки

Подходит для обработки выбранных пользователем записей. Не даёт доступа к невыделенным строкам и полям, кроме ключа

Повторный запрос

Простой и быстрый, но пользовательские отборы нужно переносить в параметры вручную — иначе результат не совпадёт со списком

Программное выполнение СКД

Учитывает все отборы и настройки списка, но требует больше кода и аккуратной настройки структуры

Замена на таблицу значений

Полный контроль и простой перебор, но теряется автообновление и стандартные команды динамического списка

Ограничения и риски при переборе данных списка

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

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

Типичные ошибки и как их проверить

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

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

Типичные ошибки
01
Выполнение текста запроса списка без переноса пользовательских отборов — обрабатываются лишние записи
02
Вызов ПолучитьОбъект() у ключа записи регистра сведений — ошибка исполнения, нужен менеджер регистра
03
Запись объектов в цикле без транзакции и без фонового задания — зависание формы и частично обработанные данные
04
Отсутствие вызова Элементы.Список.Обновить() после изменения данных — пользователь не видит результат
05
Пустая структура настроек при программном выполнении СКД — результат выводится пустым

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

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

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

Совпадает ли число обработанных записей с ожидаемым
Норма

Счётчик обработки равен количеству выделенных строк или записей по отбору

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

Часть записей пропущена — проверяйте отборы, блокировки и типы ключей

Отображение списка после обработки
Норма

После Обновить() видны изменённые значения

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

Старые значения — данные не записались или список не обновлён

Время выполнения на реальном объёме
Норма

Обработка укладывается в приемлемое время без зависания формы

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

Форма не отвечает — нужен перенос в фоновое задание

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

Можно ли получить данные текущей строки динамического списка?

Да. Используйте свойство ТекущиеДанные таблицы формы: Элементы.Список.ТекущиеДанные вернёт объект с полями текущей строки, доступными в списке. Для получения ссылки на запись есть свойство ТекущаяСтрока. Это работает только для одной активной строки, а не для перебора всех.

Как перебрать строки списка с учётом отбора, который установил пользователь?

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

Почему программное выполнение СКД возвращает пустую таблицу?

Чаще всего в настройках компоновки нет структуры: добавьте группировку детальных записей и выбранные поля. Также проверьте, что в схеме заполнены поля набора данных и переданы все обязательные параметры запроса — без значений параметров запрос может вернуть пустой результат.

Как обработать выделенные строки списка регистра сведений?

Элементы коллекции ВыделенныеСтроки для регистра сведений — это ключи записей. Объект записи получают через менеджер: МенеджерЗаписи = РегистрыСведений.ИмяРегистра.СоздатьМенеджерЗаписи(), затем заполняют его поля измерений из свойств ключа и вызывают Прочитать().

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

Выделенные строки надёжнее: набор записей зафиксирован пользователем и не изменится между отображением и обработкой. Повторный запрос может вернуть другой состав данных, если база изменилась. Для ответственных операций (проведение, изменение цен) фиксируйте ссылки заранее.

Можно ли перебрать строки динамического списка на сервере без формы?

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

Итог

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

Динамический список не хранит данные как коллекцию, поэтому прямого перебора строк не существует. Для выбранных пользователем записей используйте ВыделенныеСтроки, для полного состава с учётом отборов — программное выполнение СКД или повторный запрос с переносом отборов. Массовую запись выносите в фоновое задание и после обработки обновляйте список.