При разработке сложных отчетов в 1С программисты часто сталкиваются с необходимостью объединить несколько различных печатных форм в один файл. Объект ПакетОтображаемыхДокументов кажется идеальным инструментом для этого, так как он позволяет собрать коллекцию документов в единую сущность. Однако при вызове метода Записать() с типом файла XLSX система по умолчанию создает отдельный лист для каждого элемента пакета. В этой статье мы подробно разберем, почему это происходит, как обойти это ограничение и сохранить все данные на одной вкладке Excel, сохранив при этом корректное форматирование.
Прежде всего, проанализируем природу объекта ПакетОтображаемыхДокументов. Его основная задача — подготовить набор документов для пакетной печати или сохранения в форматы, поддерживающие многостраничность (например, PDF). Рассмотрим типовой код добавления документов в пакет:
Пакет = Новый ПакетОтображаемыхДокументов;
Для Каждого ТекСтрока ИЗ ТЗ_Документов Цикл
ТекДок = ТекСтрока.Документ.ПолучитьОбъект();
ТабДокум = ТекДок.ПечатьЛиста();
ЭлементПакета = Пакет.Состав.Добавить();
ЭлементПакета.Данные = ПоместитьВоВременноеХранилище(ТабДокум, Новый УникальныйИдентификатор);
КонецЦикла;
Пакет.Записать(ИмяФайла + ".xlsx", ТипФайлаПакетаОтображаемыхДокументов.XLSX);
Важно понимать: в платформе 1С логика работы ПакетОтображаемыхДокументов при экспорте в Excel жестко зашита — каждый элемент коллекции Состав интерпретируется как новая страница, что в терминах Excel означает новый лист (Worksheet). Настроек, позволяющих «склеить» эти листы в один в рамках этого объекта, не существует. Если нам нужен один лист, нам придется изменить стратегию формирования данных.
Самый очевидный способ решить задачу — отказаться от использования пакета и вывести все данные в один ТабличныйДокумент. Разберем, как это сделать программно. Вместо добавления во временное хранилище пакета, мы будем использовать метод Вывести().
ОбщийТабДок = Новый ТабличныйДокумент;
Для Каждого ТекСтрока ИЗ ТЗ_Документов Цикл
ТекДок = ТекСтрока.Документ.ПолучитьОбъект();
ПечатнаяФорма = ТекДок.ПечатьЛиста();
// Выводим печатную форму в общий документ
ОбщийТабДок.Вывести(ПечатнаяФорма);
// Добавляем разрыв страницы, если нужно визуальное разделение
ОбщийТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЦикла;
ОбщийТабДок.Записать(ИмяФайла + ".xlsx", ТипФайлаТабличногоДокумента.XLSX);
Проблема «кривой» верстки: Выясним причину, по которой этот метод часто не подходит. Если ваши печатные формы имеют разную ширину колонок (например, в одной форме 5 широких колонок, а в другой 15 узких), Excel не сможет адекватно отобразить их на одном листе. В 1С ТабличныйДокумент позволяет задавать ширину колонок для каждой секции отдельно, но Excel имеет одну фиксированную сетку колонок на весь лист. При экспорте 1С попытается подстроить все последующие таблицы под ширину колонок самой первой выведенной таблицы, что приведет к визуальному хаосу.
Чтобы обойти ограничение Excel по структуре колонок, применим профессиональный прием: создание «мастер-сетки». Идея заключается в том, чтобы сделать колонки основного документа очень узкими, а реальные ячейки печатных форм объединять программно так, чтобы они соответствовали нужной ширине.
Рассмотрим алгоритм реализации этого метода:
ТабличныйДокумент.Объединить() для формирования итогового вида.Этот метод трудозатратен в реализации, но он единственный гарантирует, что формы с абсолютно разной структурой будут выглядеть корректно на одном листе Excel.
Если требования позволяют использовать форматы, отличные от чистого XLSX, проанализируем возможности MHTML. Этот формат часто недооценивают, но он обладает уникальным свойством: Excel умеет открывать его как родной файл, при этом MHTML гораздо лучше сохраняет сложную верстку 1С с разной шириной колонок, объединяя все в один непрерывный лист.
ОбщийТабДок.Записать(ИмяФайла + ".mhtml", ТипФайлаТабличногоДокумента.MHTML);
После записи вы можете просто сменить расширение файла на .xls (не .xlsx), и пользователь даже не заметит разницы, открыв документ одним листом с идеальным форматированием.
Если нам принципиально нужно использовать ПакетОтображаемыхДокументов (например, из-за специфики формирования данных) и на выходе нужен именно XLSX с одним листом, мы можем прибегнуть к автоматизации самого Excel. Сначала сохраним пакет как есть (с семью листами), а затем программно объединим их.
Разберем пример кода для такой обработки:
// 1. Сохраняем временный файл с листами
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
Пакет.Записать(ИмяВременногоФайла, ТипФайлаПакетаОтображаемыхДокументов.XLSX);
// 2. Используем COM-соединение для склейки
Попытка
Excel = Новый COMОбъект("Excel.Application");
Excel.DisplayAlerts = Ложь;
Книга = Excel.Workbooks.Open(ИмяВременногоФайла);
ГлавныйЛист = Книга.Sheets(1);
// Проходим по всем листам, начиная со второго, и копируем их на первый
Для НомерЛиста = 2 По Книга.Sheets.Count Цикл
ТекущийЛист = Книга.Sheets(НомерЛиста);
ПоследняяСтрокаГлавного = ГлавныйЛист.UsedRange.Rows.Count + 2;
ТекущийЛист.UsedRange.Copy(ГлавныйЛист.Cells(ПоследняяСтрокаГлавного, 1));
КонецЦикла;
// Удаляем лишние листы
Для НомерЛиста = Книга.Sheets.Count По 2 Шаг -1 Цикл
Книга.Sheets(НомерЛиста).Delete();
КонецЦикла;
Книга.SaveAs(ИмяИтоговогоФайла);
Excel.Quit();
Исключение
Сообщить("Для работы этого метода необходим установленный Microsoft Excel");
КонецПопытки;
В ходе обсуждения часто возникает вопрос: можно ли визуально проверить ПакетОтображаемыхДокументов перед записью? К сожалению, у этого объекта нет метода Показать(). Чтобы увидеть данные, нам нужно вручную извлечь их из состава пакета.
Проанализируем способ предпросмотра:
Для Каждого Элемент Из Пакет.Состав Цикл
// Извлекаем ТабличныйДокумент из временного хранилища
ТабДок = ПолучитьИзВременногоХранилища(Элемент.Данные);
// Показываем его пользователю
ТабДок.Показать(Элемент.Наименование);
КонецЦикла;
Мы выяснили, что ПакетОтображаемыхДокументов по своей сути предназначен для создания многостраничных (многолистовых) структур. Если ваша задача — получить один лист в XLSX, рекомендуется:
Вывести(), если структуры колонок документов совпадают.ПакетаОтображаемыхДокументов.Выбор конкретного метода зависит от сложности верстки ваших печатных форм и наличия установленного Excel на сервере или клиенте.