В разработке на управляемых формах 1С часто возникает задача получить все данные, которые в данный момент отображаются в динамическом списке, с учетом всех установленных пользователем отборов динамического списка, сортировок и других настроек. Например, это может потребоваться для дальнейшей обработки, печати или выгрузки в файл (например, используя процессор вывода результата компоновки данных в JSON). Прямой доступ к строкам динамического списка, как к обычной табличной части, невозможен, так как он подгружает данные порционно. Рассмотрим, как правильно и эффективно решить эту задачу.
Проанализируем ситуацию: у нас есть форма с динамическим списком, и нам нужно программно, по нажатию кнопки, скопировать его содержимое в обычную таблицу значений. (Если же нужно обратное действие, читайте о том, как передать Таблицу Значений в Динамический Список). Основная сложность заключается в том, чтобы корректно "извлечь" запрос списка со всеми пользовательскими настройками и выполнить его для получения полного набора данных.
Самый надежный и универсальный способ получить данные динамического списка — это использовать его внутренние механизмы, основанные на системе компоновки данных (СКД). Динамический список сам по себе является результатом работы СКД. Кстати, существует способ напрямую преобразовать динамический список в отчет СКД. Наша задача — добраться до его настроек, инициализировать компоновщик макета и выполнить его, получив на выходе готовый результат.
Разберем этот процесс по шагам.
КомпоновщикНастроек. Именно в нем хранятся все пользовательские настройки: порядок, условное оформление и фильтры, включая расширенные возможности, такие как «подобно» в списке. Мы забираем их с помощью метода ПолучитьНастройки().КомпоновщикМакетаКомпоновкиДанных.Выполнить() компоновщика макета мы создаем сам макет. На вход ему нужно подать схему компоновки данных (которая лежит в основе динамического списка), полученные нами настройки и, опционально, данные расшифровки.ПроцессорКомпоновкиДанных.ПроцессорВыводаРезультатаКомпоновкиДанныхВТаблицуЗначений. Этот объект принимает результат работы процессора компоновки и выгружает его в созданную нами таблицу значений.Посмотрим на практический пример кода, который можно разместить в команде на форме. Предположим, что наш динамический список на форме называется Список.
&НаКлиенте
Процедура ВыгрузитьСписокВТЗ(Команда)
ТаблицаНаСервере = ПолучитьТаблицуСпискаНаСервере();
// Далее можно работать с полученной таблицей на клиенте
// Например, вывести количество строк
Сообщить("Выгружено строк: " + ТаблицаНаСервере.Количество());
КонецПроцедуры
&НаСервере
Функция ПолучитьТаблицуСпискаНаСервере()
// 1. Получаем настройки компоновки из динамического списка
// Объект "Список" - это реквизит формы типа ДинамическийСписок
НастройкиКД = ЭтотОбъект.Список.КомпоновщикНастроек.ПолучитьНастройки();
// 2. Создаем компоновщик макета и инициализируем его
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
// 3. Получаем схему компоновки данных из динамического списка
СхемаКД = ЭтотОбъект.Список.ПолучитьСхемуКомпоновкиДанных();
// 4. Генерируем макет на основе схемы и настроек
// Третий параметр (ДанныеРасшифровки) нам не нужен, поэтому передаем Неопределено
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКД, НастройкиКД, Неопределено);
// 5. Создаем и инициализируем процессор компоновки данных
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
// 6. Создаем таблицу, в которую будем выгружать результат
ТаблицаРезультат = Новый ТаблицаЗначений;
// 7. Создаем и настраиваем процессор вывода
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТаблицуЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультат);
// 8. Выполняем вывод результата
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// 9. Возвращаем заполненную таблицу значений
Возврат ТаблицаРезультат;
КонецФункции
Рассмотрим подробнее, что происходит в этом коде:
Клиентская процедура ВыгрузитьСписокВТЗ вызывает серверную функцию ПолучитьТаблицуСпискаНаСервере, так как вся работа с СКД и данными должна происходить на сервере. Это обеспечивает производительность и безопасность.
На сервере мы последовательно выполняем все шаги, описанные выше. Важно понимать, что объект ЭтотОбъект.Список — это наш реквизит формы с типом ДинамическийСписок. Через него мы получаем доступ ко всем необходимым данным: схеме компоновки (ПолучитьСхемуКомпоновкиДанных) и текущим настройкам (КомпоновщикНастроек.ПолучитьНастройки).
В результате работы функции мы получаем полностью заполненную ТаблицуЗначений, колонки и строки которой в точности соответствуют тому, что пользователь видел в динамическом списке на форме в момент нажатия кнопки.
В некоторых, более сложных случаях, может потребоваться не просто выгрузить данные, а получить сам текст запроса, который генерирует динамический список со всеми настройками. Это может быть полезно для отладки (для чего отлично подойдет Консоль запросов УФ) или для использования этого запроса в других механизмах. Сделать это можно похожим образом.
Основное отличие в том, что вместо процессора вывода в таблицу значений мы используем другой метод для получения информации о запросе. Это менее распространенная задача, но полезно знать о такой возможности.
&НаСервере
Функция ПолучитьТекстЗапросаСписка()
// Шаги 1-3 аналогичны предыдущему примеру
НастройкиКД = ЭтотОбъект.Список.КомпоновщикНастроек.ПолучитьНастройки();
СхемаКД = ЭтотОбъект.Список.ПолучитьСхемуКомпоновкиДанных();
// Используем специальный объект для получения информации о данных компоновки
ДанныеКомпоновки = Новый ДанныеКомпоновкиДанных(СхемаКД);
// Создаем макет компоновки, но для другого объекта
Макет = Новый МакетКомпоновкиДанных;
Макет.Выполнить(ДанныеКомпоновки, НастройкиКД);
// Из полученного макета можно извлечь текст запроса
ТекстЗапроса = Макет.НаборыДанных[0].Запрос;
Возврат ТекстЗапроса;
КонецФункции
Этот метод позволяет "заглянуть под капот" динамического списка и увидеть итоговый SQL-подобный запрос, который будет выполнен к базе данных. Однако для простой выгрузки данных первый способ является предпочтительным и более надежным.
Подведем итог. Для программной выгрузки данных из динамического списка в 1С следует придерживаться следующего алгоритма:
КомпоновщикМакетаКомпоновкиДанных, ПроцессорКомпоновкиДанных и ПроцессорВыводаРезультатаКомпоновкиДанныхВТаблицуЗначений.ДинамическийСписок.ТаблицаЗначений, полностью идентичный представлению данных в списке на форме.Этот подход гарантирует, что все пользовательские настройки, такие как отборы по полям, интервалы дат, сортировки и даже настройки условного оформления, будут учтены, и вы получите именно тот срез данных, с которым работал пользователь.