При формировании сводных отчетов часто возникает задача: выгрузить несколько связанных таблиц в один файл Excel, распределив каждую секцию на отдельный лист. Разберем типичную проблему, с которой сталкиваются разработчики при попытке решить эту задачу стандартными средствами.
Проанализируем поведение типовых инструментов. При использовании объекта ТабличныйДокумент разработчики нередко вставляют разделители страниц, рассчитывая, что программа автоматически разобьет таблицу на вкладки книги. Однако встроенный метод ТабличныйДокумент.Записать() экспортирует документ строго на один рабочий лист. Горизонтальные и вертикальные разделители предназначены исключительно для разделения печатных страниц при отправке на принтер или при предварительном просмотре, но не влияют на структуру книги Excel.
Рассмотрим два основных подхода к решению этой задачи: современный штатный механизм платформы без использования сторонних программ и классический сценарий через COM-объект Microsoft Excel.
Начиная с версии платформы 8.3.3, в 1С предусмотрен встроенный объект ПакетОтображаемыхДокументов. Это наиболее универсальный и рекомендуемый метод. Он полностью кроссплатформенный: выполняется как на клиенте, так и на сервере под управлением Windows или Linux, и не требует установки Microsoft Office.
Разберем по шагам логику реализации данного подхода:
ТабличныйДокумент.ПоместитьВоВременноеХранилище().ПакетОтображаемыхДокументов и наполняем его коллекцию Состав. Для каждого элемента указываем ссылку на данные во временном хранилище и наименование, которое станет именем листа в Excel.Записать(), указав формат ТипФайлаПакетаОтображаемыхДокументов.XLSX.Посмотрим на пример программного кода:
// Создаем пакет документов
Пакет = Новый ПакетОтображаемыхДокументов;
// Пример добавления первого листа
АдресТаб1 = ПоместитьВоВременноеХранилище(ТабДокументПродажи);
ЭлементПакета1 = Пакет.Состав.Добавить();
ЭлементПакета1.Данные = АдресТаб1;
ЭлементПакета1.Наименование = "Продажи";
// Пример добавления второго листа
АдресТаб2 = ПоместитьВоВременноеХранилище(ТабДокументВзаиморасчеты);
ЭлементПакета2 = Пакет.Состав.Добавить();
ЭлементПакета2.Данные = АдресТаб2;
ЭлементПакета2.Наименование = "Взаиморасчеты";
// Запись сформированной книги в файл XLSX
Пакет.Записать("C:\Reports\СводныйОтчет.xlsx", ТипФайлаПакетаОтображаемыхДокументов.XLSX);
Рассмотрим подробнее важные нюансы при работе со штатным пакетом:
:, \, /, ?, *, [, ]).Если решение разрабатывается для рабочей станции под управлением ОС Windows с установленным пакетом Microsoft Office, можно воспользоваться автоматизацией через COM-соединение. Данный способ заключается в сохранении каждой таблицы в отдельный промежуточный файл с последующим их объединением в общую книгу.
Посмотрим на пример реализации данного алгоритма:
ДокЭксель = Новый COMОбъект("Excel.Application");
ДокЭксель.DisplayAlerts = 0;
// Открываем основной файл, куда будем добавлять остальные листы
ОбщаяКнига = ДокЭксель.WorkBooks.Open(ИмяОсновногоФайла);
ЛистСДанными = ОбщаяКнига.Sheets(1);
ЛистСДанными.Select();
ЛистСДанными.Name = "Титульный";
Сч = 1;
Для каждого ПутьКФайлуXLS Из МассивПутейФайловXLS Цикл
Книга = ДокЭксель.WorkBooks.Open(ПутьКФайлуXLS.Значение);
ЛистСДанными = Книга.Sheets(1);
ЛистСДанными.Select();
// Формируем имя нового листа из имени файла
ИмяЛиста = СтрЗаменить(Книга.Name, СокрЛП(ПутьДляСохранения), "");
ИмяЛиста = СтрЗаменить(ИмяЛиста, ".xls", "");
ЛистСДанными.Name = ИмяЛиста;
// Копируем лист в основную книгу
ЛистСДанными.Copy(ОбщаяКнига.Sheets(Сч));
Сч = Сч + 1;
Книга.Close();
КонецЦикла;
ОбщаяКнига.Save();
ОбщаяКнига.Close();
ДокЭксель.Quit();
ДокЭксель = Неопределено;
// Удаляем временные промежуточные файлы
Для каждого ПутьКФайлуXLS Из МассивПутейФайловXLS Цикл
УдалитьФайлы(СокрЛП(ПутьКФайлуXLS.Значение));
КонецЦикла;
Проанализируем ограничения этого подхода:
EXCEL.EXE может остаться в памяти, блокируя системные ресурсы.Таким образом, для современных конфигураций 1С наиболее надежным, быстрым и кроссплатформенным решением является использование объекта ПакетОтображаемыхДокументов.