При формировании больших отчетов в 1С (особенно в типовых конфигурациях, таких как Бухгалтерия Предприятия 3.0) мы часто сталкиваемся с ситуацией, когда итоговый табличный документ получается слишком громоздким. Пользователям может быть неудобно работать с файлом Excel, содержащим сотни тысяч строк, или же возникают технические ограничения при открытии таких файлов на слабых машинах.
Рассмотрим подробно задачу разделения уже готового объекта ТабличныйДокумент на несколько файлов Excel (XLSX), ограничивая каждый файл, например, 30 000 строками. Разберем, как правильно переносить данные, сохранять форматирование и не потерять "шапку" таблицы в каждом новом файле.
Поскольку исходный документ уже сформирован (это результат стандартной обработки), у нас нет возможности вмешаться в запрос и получать данные порциями. Нам предстоит работать непосредственно с объектом ТабличныйДокумент. Существует два основных алгоритмических подхода:
Для реализации этого метода нам понадобятся следующие методы работы с табличным документом:
ПолучитьОбласть() — для взятия строки из исходника.Вывести() — для добавления области в новый документ (это лучше, чем ВставитьОбласть, так как Вывести автоматически добавляет данные в конец, не требуя расчета координат).ШиринаКолонки — свойство, которое нам придется переносить вручную.Проанализируем пошагово, как написать корректный код для этой задачи.
Важный нюанс: если мы просто нарежем таблицу на куски, только первый файл будет иметь "шапку" (названия колонок). Остальные файлы начнутся сразу с данных, что неудобно. Поэтому сначала определим область заголовка, которую будем вставлять в начало каждого нового файла.
// Предположим, исходный документ находится в переменной ИсходныйТабДок
// Пусть высота шапки составляет 5 строк (это нужно определить заранее или вычислить)
ВысотаШапки = 5;
ОбластьШапки = ИсходныйТабДок.ПолучитьОбласть(1, , ВысотаШапки);
Нам необходимо пройтись по всем строкам исходного документа, начиная со строки, следующей за шапкой. Введем переменные для контроля лимита строк.
ЛимитСтрок = 30000;
НомерФайла = 1;
СчетчикСтрокВТекущемФайле = 0;
ТекущийТабДок = Новый ТабличныйДокумент;
// Важный момент: копируем структуру колонок
// Если просто выводить области, ширина колонок будет стандартной
Для К = 1 По ИсходныйТабДок.ШиринаТаблицы Цикл
ТекущийТабДок.Область(, К, , К).ШиринаКолонки = ИсходныйТабДок.Область(, К, , К).ШиринаКолонки;
КонецЦикла;
// Выводим шапку в первый файл
ТекущийТабДок.Вывести(ОбластьШапки);
Теперь запустим цикл по данным. Обратите внимание, мы используем метод ПолучитьОбласть для каждой строки. Это позволяет захватить не только текст ячеек, но и их форматирование (шрифты, цвета, границы).
// Начинаем с первой строки данных (сразу после шапки)
Для НомерСтр = (ВысотаШапки + 1) По ИсходныйТабДок.ВысотаТаблицы Цикл
// Получаем текущую строку целиком как область
// Синтаксис: ПолучитьОбласть(<НомерВерхнейСтроки>, <НомерЛевойКолонки>, <НомерНижнейСтроки>, <НомерПравойКолонки>)
ОбластьСтрока = ИсходныйТабДок.ПолучитьОбласть(НомерСтр, , НомерСтр);
// Выводим строку в текущий накопительный документ
ТекущийТабДок.Вывести(ОбластьСтрока);
СчетчикСтрокВТекущемФайле = СчетчикСтрокВТекущемФайле + 1;
// Проверяем, не достигли ли мы лимита
Если СчетчикСтрокВТекущемФайле >= ЛимитСтрок Тогда
// Формируем имя файла
ИмяФайла = "C:\Reports\Отчет_Часть_" + НомерФайла + ".xlsx";
ТекущийТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
// Очищаем память и готовим переменные для следующей порции
ТекущийТабДок = Неопределено; // Помогаем сборщику мусора
ТекущийТабДок = Новый ТабличныйДокумент;
// Снова копируем ширину колонок для нового документа
Для К = 1 По ИсходныйТабДок.ШиринаТаблицы Цикл
ТекущийТабДок.Область(, К, , К).ШиринаКолонки = ИсходныйТабДок.Область(, К, , К).ШиринаКолонки;
КонецЦикла;
// Снова выводим шапку в начало нового файла
ТекущийТабДок.Вывести(ОбластьШапки);
СчетчикСтрокВТекущемФайле = 0;
НомерФайла = НомерФайла + 1;
КонецЕсли;
КонецЦикла;
// Сохраняем "хвост" данных (последний кусок, который мог быть меньше 30000 строк)
Если СчетчикСтрокВТекущемФайле > 0 Тогда
ИмяФайла = "C:\Reports\Отчет_Часть_" + НомерФайла + ".xlsx";
ТекущийТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
КонецЕсли;
Рассмотрим несколько нюансов, которые помогут избежать ошибок при выполнении этого кода:
Неопределено перед созданием нового объекта (Новый ТабличныйДокумент) — хорошая практика, сигнализирующая платформе, что память можно освободить.Вывести() корректно переносит уровень группировки, но целостность иерархии в рамках одного файла будет зависеть от места разрыва.ПолучитьОбласть переносит свойства ячеек, а параметры печати (ориентация страницы, поля) нужно задавать для свойства ТекущийТабДок отдельно, если это требуется.Используя данный подход, вы сможете автоматизировать выгрузку даже очень объемных результатов отчетов, разбивая их на удобные для пользователей части.