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