В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача автоматизации выгрузки данных. Одной из наиболее трудоемких операций является сохранение иерархических структур, таких как ДеревоЗначений, в формат Excel. Стандартная команда «Вывести список» удобна для пользователя, но её крайне сложно вызвать программно без участия человека. Особенно это актуально для фоновых заданий или алгоритмов, которые должны отправить отчет по электронной почте сразу после завершения работы. Для интерактивного экспорта списков и таблиц из интерфейса подойдёт подсистема сохранения данных табличных частей форм в Excel.
В этой статье мы разберем наиболее эффективные способы решения данной задачи: от классической рекурсии до использования Системы компоновки данных (СКД).
Этот метод является самым гибким и понятным. Суть заключается в последовательном переборе строк дерева и выводе их в ТабличныйДокумент с использованием встроенных механизмов группировки строк. Проанализируем реализацию этого подхода.
Для начала нам необходимо создать рекурсивную процедуру, которая будет обходить каждый уровень дерева. Важным моментом здесь является использование метода Вывести() с указанием уровня группировки.
// Процедура для рекурсивного обхода строк дерева
Процедура ПечатьДерева(СтрокиДерева, Уровень = 0, Колонки, ТабДок, Секция)
Для Каждого Стр Из СтрокиДерева Цикл
НомерКолонки = 0;
// Для визуального выделения иерархии в первой колонке можно добавить отступы
Отступ = "";
Для н = 1 По Уровень Цикл
Отступ = Отступ + " ";
КонецЦикла;
Для Каждого КЛ Из Колонки Цикл
НомерКолонки = НомерКолонки + 1;
ЗначениеЯчейки = Стр[КЛ.Имя];
// Записываем данные в ячейку. Если это первая колонка — добавляем отступ.
Если НомерКолонки = 1 Тогда
Секция.Область(1, НомерКолонки).Текст = Отступ + Строка(ЗначениеЯчейки);
Иначе
Секция.Область(1, НомерКолонки).Текст = ЗначениеЯчейки;
КонецЕсли;
КонецЦикла;
// Выводим секцию в табличный документ, указывая текущий уровень для автогруппировки
ТабДок.Вывести(Секция, Уровень + 1);
// Рекурсивно вызываем эту же процедуру для подчиненных строк
ПечатьДерева(Стр.Строки, Уровень + 1, Колонки, ТабДок, Секция);
КонецЦикла;
КонецПроцедуры
После того как вспомогательная процедура готова, рассмотрим основную логику подготовки документа. Нам нужно инициализировать ТабличныйДокумент, сформировать заголовки и запустить процесс выгрузки.
Процедура СформироватьИСохранитьФайл(ДанныеДерева)
ТабДок = Новый ТабличныйДокумент;
// 1. Формируем заголовок таблицы
СекцияЗаголовка = ТабДок.ПолучитьОбласть("R1");
НомерКолонки = 0;
Для Каждого КЛ Из ДанныеДерева.Колонки Цикл
НомерКолонки = НомерКолонки + 1;
СекцияЗаголовка.Область(1, НомерКолонки).Текст = КЛ.Заголовок;
// Можно добавить оформление заголовка
СекцияЗаголовка.Область(1, НомерКолонки).Шрифт = Новый Шрифт(,,Истина);
КонецЦикла;
ТабДок.Вывести(СекцияЗаголовка);
// 2. Подготовка к выводу строк
СекцияСтроки = ТабДок.ПолучитьОбласть("R2");
ТабДок.НачатьАвтогруппировкуСтрок();
// Запуск рекурсии (передаем коллекцию строк верхнего уровня)
ПечатьДерева(ДанныеДерева.Строки, 0, ДанныеДерева.Колонки, ТабДок, СекцияСтроки);
ТабДок.ЗакончитьАвтогруппировкуСтрок();
// 3. Настройка отображения (сворачивание уровней)
ТабДок.ПоказатьУровниГруппировокСтрок(1);
// 4. Сохранение в формате Excel
ИмяФайла = "ВыгрузкаДерева_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".xlsx";
ПолныйПуть = КаталогВременныхФайлов() + ИмяФайла;
ТабДок.Записать(ПолныйПуть, ТипФайлаТабличногоДокумента.XLSX);
Сообщить("Файл успешно сохранен: " + ПолныйПуть);
КонецПроцедуры
Если дерево значений имеет сложную структуру или требуется быстро менять состав выводимых полей, лучше использовать СКД. Этот метод считается более "правильным" в архитектуре 1С, так как разделяет данные и представление. Для упрощения программной работы со схемами можно применить модуль-обёртку над объектной моделью СКД.
Разберем алгоритм работы с СКД через внешний набор данных:
ВнешнееДерево) должно совпадать с ключом в структуре внешних наборов.Программный код для вывода будет выглядеть следующим образом:
// Пример вывода через СКД
Схема = ПолучитьМакет("МояСхемаКомпоновки"); // Схема должна быть в макетах обработки
Настройки = Схема.НастройкиПоУмолчанию;
ДанныеДляВывода = Новый Структура("ВнешнееДерево", МоеДеревоЗначений);
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки,,, Тип("ГенераторМакетаКомпоновкиДанныхДляРезультатаКомпоновки"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ДанныеДляВывода);
ТабДок = Новый ТабличныйДокумент;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабДок);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
Рассмотрим несколько профессиональных советов, которые помогут сделать выгрузку быстрее и качественнее:
1. Выбор формата файла. Всегда используйте ТипФайлаТабличногоДокумента.XLSX вместо устаревшего XLS. Формат XLSX поддерживает более 1 миллиона строк, лучше сжимает данные и корректнее сохраняет форматирование ячеек (цвета, шрифты, границы).
2. Скорость работы. Обращение к каждой ячейке через Область(р, к).Текст — это медленная операция, если строк в дереве больше нескольких тысяч. Чтобы ускорить процесс, рекомендуется подготовить в макете целую строку-шаблон и выводить её целиком через ТабДок.Вывести(Секция), предварительно заполнив параметры в этой секции.
3. Группировки. Метод НачатьАвтогруппировкуСтрок() работает только в паре с параметром уровня в методе Вывести(). Если вы забудете указать уровень в ТабДок.Вывести(Секция, Уровень), иерархические "плюсики" в левой части таблицы (и в Excel) не появятся.
4. Оформление. Чтобы пользователь сразу видел структуру, используйте свойство ПоказатьУровниГруппировокСтрок(1). Это автоматически свернет дерево до первого уровня при открытии файла.
5. Работа на сервере. Помните, что КаталогВременныхФайлов() на сервере (под Linux или Windows) — это не то же самое, что временный каталог на клиенте. Если вы формируете файл в фоновом задании, убедитесь, что у службы 1С есть права на запись в эту директорию.
Проанализировав вышеописанные ситуации, мы выяснили, что для простых задач достаточно рекурсивного обхода, а для сложных отчетов с иерархией лучше применять СКД. Оба метода позволяют полностью исключить ручные действия пользователя и автоматизировать процесс сохранения данных в Excel.