Как разделить ТабличныйДокумент на части по 30000 строк для сохранения каждой в xlsx?

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

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

Рассмотрим подробно задачу разделения уже готового объекта ТабличныйДокумент на несколько файлов Excel (XLSX), ограничивая каждый файл, например, 30 000 строками. Разберем, как правильно переносить данные, сохранять форматирование и не потерять "шапку" таблицы в каждом новом файле.

Основные подходы к решению

Поскольку исходный документ уже сформирован (это результат стандартной обработки), у нас нет возможности вмешаться в запрос и получать данные порциями. Нам предстоит работать непосредственно с объектом ТабличныйДокумент. Существует два основных алгоритмических подхода:

  1. Метод исключения (копирование и удаление). Мы создаем полную копию документа, а затем удаляем из нее все "лишнее". Этот метод прост в реализации, но потребляет огромное количество оперативной памяти, так как требует дублирования тяжелого объекта. Мы не будем рекомендовать его для очень больших отчетов.
  2. Метод переноса (построчная сборка). Мы создаем новые, пустые табличные документы и переносим в них строки из исходника. Как только лимит строк достигнут — сохраняем файл, очищаем память и начинаем наполнять новый документ. Этот метод мы и разберем детально, так как он наиболее оптимален.

Алгоритм построчного переноса

Для реализации этого метода нам понадобятся следующие методы работы с табличным документом:

Проанализируем пошагово, как написать корректный код для этой задачи.

Этап 1: Подготовка и определение заголовка

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


// Предположим, исходный документ находится в переменной ИсходныйТабДок
// Пусть высота шапки составляет 5 строк (это нужно определить заранее или вычислить)
ВысотаШапки = 5;
ОбластьШапки = ИсходныйТабДок.ПолучитьОбласть(1, , ВысотаШапки);

Этап 2: Организация цикла обхода

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


ЛимитСтрок = 30000;
НомерФайла = 1;
СчетчикСтрокВТекущемФайле = 0;
ТекущийТабДок = Новый ТабличныйДокумент;

// Важный момент: копируем структуру колонок
// Если просто выводить области, ширина колонок будет стандартной
Для К = 1 По ИсходныйТабДок.ШиринаТаблицы Цикл
    ТекущийТабДок.Область(, К, , К).ШиринаКолонки = ИсходныйТабДок.Область(, К, , К).ШиринаКолонки;
КонецЦикла;

// Выводим шапку в первый файл
ТекущийТабДок.Вывести(ОбластьШапки);

Этап 3: Перенос строк и сохранение файлов

Теперь запустим цикл по данным. Обратите внимание, мы используем метод ПолучитьОбласть для каждой строки. Это позволяет захватить не только текст ячеек, но и их форматирование (шрифты, цвета, границы).


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

КонецЦикла;

// Сохраняем "хвост" данных (последний кусок, который мог быть меньше 30000 строк)
Если СчетчикСтрокВТекущемФайле > 0 Тогда
    ИмяФайла = "C:\Reports\Отчет_Часть_" + НомерФайла + ".xlsx";
    ТекущийТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
КонецЕсли;

Важные замечания по производительности

Рассмотрим несколько нюансов, которые помогут избежать ошибок при выполнении этого кода:

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

Используя данный подход, вы сможете автоматизировать выгрузку даже очень объемных результатов отчетов, разбивая их на удобные для пользователей части.

← На главную