Как выгрузить несколько табличных документов с формы в один файл Excel в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке отчетов и обработок в 1С часто возникает задача: на форме отображаются сразу два, три или более полей табличного документа, и пользователю требуется выгрузить их все в один файл Excel. Стандартная попытка вызвать метод Записать() по очереди для каждого табличного документа приводит к тому, что в итоговом файле остается только последняя таблица, так как каждый вызов перезаписывает файл на диске.

Выясним причину такого поведения и подробно разберем все способы решения этой задачи: сохранение таблиц на отдельные листы книги с помощью специального объекта платформы, а также их объединение на одном общем листе.

Выясним причину: почему метод Записать() сохраняет только одну таблицу

Проанализируем ситуацию: стандартный объект ТабличныйДокумент в платформе 1С:Предприятие представляет собой отдельный документ (аналог одного листа). Когда мы выполняем команду сохранения:


ТабДок1.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
ТабДок2.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
ТабДок3.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);

Платформа не добавляет новые листы в существующий файл, а полностью перезаписывает его с нуля при каждом вызове. В результате на диске остается только результат работы третьей строки. Чтобы получить полноценную книгу Excel, необходимо либо использовать штатный контейнер пакетов документов, либо объединять таблицы программно.

Способ 1. Вывод таблиц на разные листы книги через ПакетОтображаемыхДокументов

Начиная с версии платформы 8.3.12, разработчикам доступен нативный механизм выгрузки нескольких табличных документов в многостраничный файл Excel без использования сторонних библиотек и COM-объектов. Для этого применяется объект ПакетОтображаемыхДокументов.

Разберем по шагам, как устроен этот механизм:

  1. Создаем экземпляр объекта ПакетОтображаемыхДокументов.
  2. Помещаем каждый табличный документ во временное хранилище и получаем его адрес. Важный нюанс: свойство Данные элемента состава пакета принимает именно строковый адрес во временном хранилище, а не сам объект ТабличныйДокумент. Передача объекта напрямую вызовет ошибку.
  3. Добавляем элементы в коллекцию Состав пакета, передавая полученный адрес в свойство Данные, а имя будущего листа Excel — в свойство Наименование.
  4. Вызываем метод Записать() уже у самого пакета, указав тип файла ТипФайлаПакетаОтображаемыхДокументов.XLSX.

Посмотрим на пример процедуры на сервере, которая формирует и сохраняет файл:


&НаСервере
Процедура СохранитьТриТаблицыВExcelНаСервере(ПутьКФайлу)
    
    Пакет = Новый ПакетОтображаемыхДокументов;
    
    // Лист 1
    Элемент1 = Пакет.Состав.Добавить();
    Элемент1.Данные = ПоместитьВоВременноеХранилище(Элементы.ПолеТабДок1.ТабличныйДокумент);
    Элемент1.Наименование = "Отчет по продажам";
    
    // Лист 2
    Элемент2 = Пакет.Состав.Добавить();
    Элемент2.Данные = ПоместитьВоВременноеХранилище(Элементы.ПолеТабДок2.ТабличныйДокумент);
    Элемент2.Наименование = "Взаиморасчеты";
    
    // Лист 3
    Элемент3 = Пакет.Состав.Добавить();
    Элемент3.Данные = ПоместитьВоВременноеХранилище(Элементы.ПолеТабДок3.ТабличныйДокумент);
    Элемент3.Наименование = "Остатки на складах";
    
    // Сохраняем все листы в один файл
    Пакет.Записать(ПутьКФайлу, ТипФайлаПакетаОтображаемыхДокументов.XLSX);
    
КонецПроцедуры

Рассмотрим подробнее правила задания свойства Наименование для листов Excel. Чтобы файл успешно открывался и не вызывал системных сбоев, необходимо соблюдать ограничения формата Excel:

  1. Длина наименования листа не должна превышать 31 символ.
  2. Имена всех листов в рамках одного пакета должны быть уникальными.
  3. В названии запрещено использовать специальные символы: \ / ? * [ ] :.

Способ 2. Объединение трех таблиц на одном листе

Если бизнес-логика требует расположить данные всех трех полей на одном листе (например, друг под другом с небольшим отступом или в виде сводной таблицы), нам потребуется создать новый результирующий ТабличныйДокумент и последовательно перенести в него данные.

Разберем по шагам реализацию вертикального объединения:

  1. Инициализируем результирующий объект ТабличныйДокумент.
  2. Методом Вывести() последовательно добавляем в него исходные таблицы. Метод Вывести() добавляет строки ниже уже существующих. Если требуется расположить таблицы рядом по горизонтали, используется метод Присоединить().
  3. При необходимости вставляем между таблицами пустые строки или разделители страниц.
  4. Вызываем метод Записать() результирующего табличного документа.

Посмотрим на пример реализации объединения друг под другом:


&НаСервере
Процедура ОбъединитьИСохранитьНаОдинЛист(ПутьКФайлу)
    
    ИтоговыйТабДок = Новый ТабличныйДокумент;
    
    // Выводим первую таблицу
    ИтоговыйТабДок.Вывести(ТабДок1);
    
    // Добавляем пустую строку-разделитель
    ПустаяТаблица = Новый ТабличныйДокумент;
    ПустаяТаблица.ВывестиСтроку();
    ИтоговыйТабДок.Вывести(ПустаяТаблица);
    
    // Выводим вторую таблицу
    ИтоговыйТабДок.Вывести(ТабДок2);
    ИтоговыйТабДок.Вывести(ПустаяТаблица);
    
    // Выводим третью таблицу
    ИтоговыйТабДок.Вывести(ТабДок3);
    
    // Записываем единый лист в файл Excel
    ИтоговыйТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
    
КонецПроцедуры

Важный момент при объединении: у результирующего листа будет общая сетка колонок. Если у первой таблицы ширина первой колонки составляет 15 единиц, а у второй таблицы — 40 единиц, одна из таблиц может визуально исказиться (текст обрежется или ячейка станет слишком широкой). Если у таблиц кардинально разная структура и ширина колонок, рекомендуется использовать Способ 1 с выводом на разные листы.

Способ 3. Использование COM-объекта Excel.Application (для устаревших платформ)

Если решение разрабатывается на платформе версии ниже 8.3.12, где у объекта ПакетОтображаемыхДокументов еще не было метода Записать() в формат XLSX, объединить листы можно через Windows COM-соединение с приложением Excel.

Схема решения в этом случае выглядит так:

  1. Каждый табличный документ сохраняется во временный файл XLSX через стандартный метод Записать().
  2. Через Новый COMОбъект("Excel.Application") открывается сессия Microsoft Excel.
  3. Создается итоговая книга, в которую копируются листы из сохраненных временных файлов.
  4. Итоговая книга сохраняется, временные файлы удаляются, а процесс Excel корректно закрывается.

Ограничения COM-подхода: данный метод работает исключительно в операционной системе Windows, требует наличия установленного пакета Microsoft Office на клиенте или сервере и не может использоваться в веб-клиенте или на серверах под управлением Linux. Поэтому на современных версиях платформы всегда следует отдавать предпочтение объекту ПакетОтображаемыхДокументов.

← На главную