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

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

Как получить элементы динамического списка в 1С

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

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

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

Ниже разобраны рабочие способы получения данных из динамического списка: от простого чтения текущей строки до программного выполнения запроса списка с переносом отборов. Для каждого приёма указаны условия применения, ограничения и типичные ошибки.

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

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

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

Получение текущей строки списка

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

ТекущиеДанные = Элементы.Список.ТекущиеДанные;

Если ТекущиеДанные = Неопределено Тогда

Возврат; // строка не выбрана

КонецЕсли;

СсылкаНаДокумент = ТекущиеДанные.Ссылка;

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

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

Получение выделенных строк

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

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

ДанныеСтроки = Элементы.Список.ДанныеСтроки(КлючСтроки);

// ДанныеСтроки.Ссылка, ДанныеСтроки.Номер и т.д.

КонецЦикла;

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

Порядок действий для групповой обработки
  1. 1
    Проверьте, что Элементы.Список.ВыделенныеСтроки.Количество() больше нуля
  2. 2
    Пройдите циклом по выделенным строкам и соберите ссылки в массив
  3. 3
    Передайте массив в серверную процедуру одним вызовом
  4. 4
    На сервере выполните обработку в транзакции, если изменяются данные
  5. 5
    Обновите список: Элементы.Список.Обновить()

Получение всех элементов списка через повторное выполнение запроса

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

&НаСервере

Функция ПолучитьДанныеСписка()

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

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

// Перенос параметров

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

Если Параметр.Использование Тогда

Запрос.УстановитьПараметр(Параметр.Параметр, Параметр.Значение);

КонецЕсли;

КонецЦикла;

Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

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

Получение данных через схему компоновки данных

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

&НаСервере

Функция ВыгрузитьДанныеСписка()

Схема = Элементы.Список.ПолучитьИсполняемуюСхемуКомпоновкиДанных();

Настройки = Элементы.Список.ПолучитьИсполняемыеНастройкиКомпоновкиДанных();

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

Макет = КомпоновщикМакета.Выполнить(Схема, Настройки, , ,

Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

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

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

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

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

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

ПроцессорВывода.Вывести(ПроцессорКомпоновки);

Возврат Результат;

КонецФункции

Этот код возвращает таблицу значений, полностью соответствующую содержимому списка с текущими отборами. Именно так реализуются типовые механизмы выгрузки списков в табличный документ. Учтите, что метод выполняется только на сервере и при больших объёмах данных может занять заметное время и память — для очень крупных выборок добавляйте ограничения или предупреждайте пользователя.

Особые случаи: регистры сведений и динамическое считывание

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

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

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

Проверка результата и отладка

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

Полезный приём отладки — вывести текст итогового запроса из макета компоновки (Макет.НаборыДанных) и выполнить его в консоли запросов. Это позволяет увидеть, какие именно условия применила платформа, и быстро найти потерянный отбор или параметр.

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

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

Количество записей в выгруженной таблице
Норма

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

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

Меньше или больше — не перенесены отборы или параметры

Значения полей в первых строках
Норма

Совпадают с отображаемыми в списке

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

Пустые поля — колонка не входит в выборку запроса

Время выполнения выгрузки
Норма

Секунды при типовом объёме отобранных данных

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

Десятки секунд и рост памяти — выборка слишком велика, нужны отборы

FAQ

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

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

Почему ТекущиеДанные возвращает Неопределено?

Строка не выбрана: список пуст, фокус находится вне таблицы или список ещё не загрузился. Всегда проверяйте результат на Неопределено перед обращением к полям.

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

Используйте ТекущиеДанные с полями измерений напрямую или сформируйте ключ записи (РегистрыСведений.ИмяРегистра.СоздатьКлючЗаписи) по значениям измерений и периода. Свойства Ссылка у записей регистра сведений нет.

Чем отличается ТекущаяСтрока от ТекущиеДанные?

ТекущаяСтрока — это ключ строки (для списков с основной таблицей обычно ссылка), а ТекущиеДанные — объект со всеми полями строки, доступными в выборке списка. Если нужна только ссылка, достаточно ТекущаяСтрока.

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

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

Почему повторно выполненный запрос возвращает другие данные, чем список?

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

Итог

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

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