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

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

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

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

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

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

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

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

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

Из этого следуют два важных ограничения. Во-первых, у реквизита списка нет методов вроде Количество() или индексированного доступа к строкам. Во-вторых, даже если визуально в списке тысяча строк, программно «дотянуться» можно только к тем данным, которые платформа отдала форме, — в первую очередь к текущей и выделенным строкам.

Поэтому универсальное правило звучит так: если нужны все данные списка — нужно выполнить его запрос заново программно, а не искать способ «вытащить» строки из реквизита формы. Это не дублирование работы: запрос выполняется на сервере и при корректных отборах работает быстро.

Как прочитать текущую и выделенные строки списка

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

&НаКлиенте

Процедура ПоказатьТекущуюСтроку(Команда)

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

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

ПоказатьПредупреждение(, "Строка не выбрана");

Возврат;

КонецЕсли;

Сообщить("Ссылка: " + ТекущиеДанные.Ссылка);

КонецПроцедуры

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

&НаКлиенте

Процедура ОбработатьВыделенные(Команда)

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

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

Сообщить(Строка(КлючСтроки));

КонецЦикла;

КонецПроцедуры

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

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

&НаСервере

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Порядок действий
  1. 1
    Убедитесь, что обработка выполняется на сервере: директива &НаСервере или вызов серверной процедуры
  2. 2
    Получите исполняемую схему и настройки через методы элемента формы Список
  3. 3
    Сформируйте макет компоновки с генератором для коллекции значений
  4. 4
    Выведите результат процессором вывода в таблицу значений
  5. 5
    Проверьте количество строк и наличие нужных колонок в результате

Альтернатива: отдельный запрос с теми же отборами

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

&НаСервере

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

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка,

| Номенклатура.Артикул КАК Артикул

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| НЕ Номенклатура.ПометкаУдаления";

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

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

Сравнение вариантов

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

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

Отдельный запрос

Подходит для фиксированных условий и фоновых обработок. Ограничение: пользовательские настройки списка не учитываются

ТекущиеДанные / ВыделенныеСтроки

Подходит для действий над выбранными строками. Ограничение: доступны только выделенное и выведенные в список поля

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

Как учесть отборы и параметры динамического списка

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

Программно добавить отбор к списку можно так:

&НаСервере

Процедура УстановитьОтборПоОрганизации(Организация)

ЭлементОтбора = Список.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(

Тип("ЭлементОтбораКомпоновкиДанных"));

ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Организация");

ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;

ЭлементОтбора.ПравоеЗначение = Организация;

ЭлементОтбора.Использование = Истина;

КонецПроцедуры

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

Проверка результата и типичные ошибки

После получения данных обязательно проверьте, что результат соответствует ожиданиям: количество строк совпадает с тем, что видно в списке (с учётом отборов), нужные колонки присутствуют, а ссылки не пустые. Расхождение почти всегда означает, что учтены не все отборы или использована не та схема.

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

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

Количество строк результата
Норма

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

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

Строк больше — не учтены отборы; меньше — лишние условия

Состав колонок
Норма

Все нужные поля присутствуют в таблице значений

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

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

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

Ссылки заполнены и разыменовываются

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

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

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

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

Ограничения и частные случаи

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

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

Итог

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

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

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

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

Штатного свойства «количество строк» у динамического списка нет. Практичный вариант — выполнить запрос с теми же отборами, выбрав только Количество(Различные Ссылка), либо выполнить СКД программно и посчитать строки результата. Первый способ дешевле по ресурсам.

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

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

Как получить данные списка в фоновом задании?

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

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

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

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

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

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

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