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