При работе с большими отчетами в 1С часто возникает необходимость не просто выгрузить данные в Excel, но и разделить их на несколько отдельных файлов или листов по определенному критерию, например, по количеству строк. Это может быть актуально, когда общий объем данных слишком велик для одного файла или если требуется отправка частей отчета разным получателям. В данном материале мы рассмотрим несколько подходов к решению этой задачи, начиная с прямого программного разделения табличного документа и заканчивая более сложными методами для оптимизации работы с очень большими объемами данных.
Основной вопрос, который мы решаем, заключается в том, как программно взять сформированный табличный документ и разбить его на части, сохраняя каждую часть в отдельный файл Excel. Это особенно актуально для неуправляемых форм, где возможности пользователя по интерактивной обработке больших отчетов могут быть ограничены.
Для реализации этой задачи мы будем использовать методы объекта ТабличныйДокумент, который является основным представлением отчетов и печатных форм в 1С. Наша стратегия будет заключаться в пошаговом извлечении определенных областей из исходного табличного документа и сохранении каждой из этих областей в новый, временный табличный документ, который затем будет записан в отдельный файл Excel.
ТабличныйДокумент, содержащий весь отчет. Пусть это будет переменная Таблица.КоличествоСтрокНа.Таблица.ПолучитьОбласть(), который позволяет извлечь прямоугольную область из существующего табличного документа.ТабличныйДокумент.Рассмотрим пример кода, который демонстрирует этот подход:
// Предполагаем, что "Таблица" - это наш исходный ТабличныйДокумент, содержащий весь отчет.
// Например, Таблица = Отчет.Сформировать();
// Задаем количество строк в каждом выходном файле
КоличествоСтрокНа = 10000; // Пример: по 10 тысяч строк в каждом файле
// Определяем общее количество строк в исходной таблице
ВысотаИсходнойТаблицы = Таблица.ВысотаТаблицы;
// Определяем количество порций (файлов)
КоличествоПорций = Цел(ВысотаИсходнойТаблицы / КоличествоСтрокНа);
Если ВысотаИсходнойТаблицы % КоличествоСтрокНа > 0 Тогда
КоличествоПорций = КоличествоПорций + 1;
КонецЕсли;
Для НомерПорции = 1 По КоличествоПорций Цикл
// Определяем начальную строку для текущей порции
НачальнаяСтрока = (НомерПорции - 1) * КоличествоСтрокНа + 1;
// Определяем конечную строку для текущей порции
КонечнаяСтрока = Мин(НомерПорции * КоличествоСтрокНа, ВысотаИсходнойТаблицы);
// Создаем новый табличный документ для текущей порции
ТабПорция = Новый ТабличныйДокумент;
// Получаем область из исходного табличного документа
ОбластьДляВывода = Таблица.ПолучитьОбласть(НачальнаяСтрока, 1, КонечнаяСтрока, Таблица.ШиринаТаблицы);
// Выводим полученную область в новый табличный документ порции
ТабПорция.Вывести(ОбластьДляВывода);
// Формируем имя файла для текущей порции
ИмяОчередногоФайла = "Отчет_Часть_" + Формат(НомерПорции, "ЧГ=0") + ".xlsx";
// Сохраняем табличный документ порции в файл Excel
ТабПорция.Записать(ИмяОчередногоФайла, ТипТабличногоДокумента.XLSX);
Сообщить("Файл " + ИмяОчередногоФайла + " успешно сохранен.");
КонецЦикла;
Сообщить("Выгрузка отчета в несколько файлов завершена.");
Данный код позволяет итеративно обрабатывать большой табличный документ, извлекая из него заданные порции данных и сохраняя их в отдельные файлы Excel. Мы используем функцию Мин() для корректной обработки последней порции, которая может содержать меньше строк, чем заданное КоличествоСтрокНа. Тип файла XLSX является современным форматом Excel.
Хотя вышеописанный метод является прямым ответом на исходный вопрос, при работе с очень большими отчетами, превышающими десятки тысяч или сотни тысяч строк, могут возникать проблемы с производительностью и потреблением памяти. Рассмотрим дополнительные, более оптимизированные подходы, которые расширяют возможности выгрузки.
Начиная с версии 1С 8.3.12, нам стала доступна возможность программно сохранять несколько табличных документов в один файл Excel, при этом каждый табличный документ будет расположен на отдельном листе. Этот подход идеально подходит, если мы хотим не разбить отчет на отдельные файлы, а собрать несколько логически связанных частей или версий одного отчета в единый многостраничный файл Excel.
Для реализации этого метода мы будем использовать объекты ПакетОтображаемыхДокументов и ЭлементПакетаОтображаемыхДокументов. Каждый ЭлементПакетаОтображаемыхДокументов представляет собой отдельный лист в итоговом файле Excel, и мы можем задать ему уникальное имя с помощью свойства Наименование.
ПакетОтображаемыхДокументов.ЭлементПакетаОтображаемыхДокументов.Документ элемента наш сформированный ТабличныйДокумент, а свойству Наименование — желаемое имя листа в Excel.Записать() объекта ПакетОтображаемыхДокументов для сохранения всех документов в один файл Excel.Этот способ является более структурированным и удобным решением для создания многостраничных отчетов в Excel, чем ручное копирование областей, если целью является объединение, а не разделение на отдельные файлы.
// Пример использования для сохранения нескольких табличных документов в один файл Excel на разных листах
ПакетДокументов = Новый ПакетОтображаемыхДокументов;
// Таблица1 - первый отчет или порция
ЭлементПакета1 = ПакетДокументов.Элементы.Добавить();
ЭлементПакета1.Документ = Таблица1;
ЭлементПакета1.Наименование = "Общая сводка";
// Таблица2 - второй отчет или порция
ЭлементПакета2 = ПакетДокументов.Элементы.Добавить();
ЭлементПакета2.Документ = Таблица2;
ЭлементПакета2.Наименование = "Детализация продаж";
// Таблица3 - третий отчет или порция
ЭлементПакета3 = ПакетДокументов.Элементы.Добавить();
ЭлементПакета3.Документ = Таблица3;
ЭлементПакета3.Наименование = "Список товаров";
// Сохраняем пакет в один файл Excel
ПакетДокументов.Записать("ПолныйОтчет_Многолистовой.xlsx", ТипТабличногоДокумента.XLSX);
Сообщить("Многолистовой файл Excel успешно создан.");
Когда мы сталкиваемся с отчетами, объем которых измеряется миллионами строк или десятками мегабайт, стандартные методы выгрузки могут приводить к проблемам "Недостаточно памяти на клиенте" или "Недостаточно памяти на сервере", а также к крайне низкой производительности. В таких случаях нам необходимо применять более продвинутые и ресурсоэффективные подходы.
Рассмотрим два ключевых метода:
Потоковая запись в CSV: Вместо формирования всего табличного документа в памяти, что является затратной операцией, мы можем построчно получать результаты запроса и записывать их напрямую в текстовый файл на сервере. Формат CSV (Comma Separated Values) идеально подходит для этой цели, так как он является простым текстовым представлением табличных данных.
ЗаписьТекста. Этот объект позволяет нам открыть файл на сервере и построчно записывать в него данные, что минимизирует потребление памяти.Пример концептуального кода:
// Предполагаем, что у нас есть Запрос, который возвращает данные.
// Запрос = Новый Запрос("ВЫБРАТЬ ...");
// РезультатЗапроса = Запрос.Выполнить();
// Выборка = РезультатЗапроса.Выбрать();
ИмяФайлаCSV = КаталогВременныхФайлов() + "Отчет_Потоковый.csv";
Запись = Новый ЗаписьТекста(ИмяФайлаCSV, КодировкаТекста.UTF8, , Истина); // Истина для добавления BOM
// Записываем заголовки
СписокПолей = "Поле1;Поле2;Поле3"; // Замените на реальные имена полей
Запись.ЗаписатьСтроку(СписокПолей);
Пока Выборка.Следующий() Цикл
СтрокаCSV = Строка(Выборка.Поле1) + ";" + Строка(Выборка.Поле2) + ";" + Строка(Выборка.Поле3);
Запись.ЗаписатьСтроку(СтрокаCSV);
КонецЦикла;
Запись.Закрыть();
Сообщить("CSV файл успешно создан: " + ИмяФайлаCSV);
Архивация и передача: Сформированный CSV файл, даже если он очень большой, можно заархивировать, используя встроенные средства 1С (объект ЗаписьZipФайла). Это позволяет уменьшить размер файла, что критично при его передаче по сети. После архивации файл передается на клиентскую сторону, где пользователь может его распаковать и открыть в Excel.
ЗаписьZipФайла для архивации и Файл или другие механизмы для передачи.Еще один способ выгрузки данных, который предоставляет нам максимальный контроль над форматированием и структурой Excel-файла, – это программная работа с Excel через COM-объекты. Мы можем создать экземпляр приложения Excel (Excel.Application) и напрямую управлять его объектами (рабочими книгами, листами, ячейками, диапазонами).
Excel = Новый COMОбъект("Excel.Application");Excel.Cells(Строка, Колонка).Value = Значение).Однако для очень больших объемов данных частые обращения к COM-объектам могут значительно замедлять процесс. Каждое такое обращение — это межпроцессное взаимодействие, которое требует времени. Рекомендуется минимизировать количество таких вызовов, например, записывать данные блоками (диапазонами), а не по одной ячейке. Пример реализации блочной работы можно изучить в обработке для чтения и записи области листа Excel через COM.
Важный момент: Этот метод требует установленного Microsoft Excel на машине, где выполняется код (чаще всего на клиентской). На сервере этот метод может быть нежелателен или вовсе неработоспособен из-за отсутствия GUI и специфики серверных операционных систем.
Независимо от выбранного метода выгрузки, ключевым фактором производительности является сама подготовка данных в 1С. Если данные формируются медленно, то и выгрузка будет медленной. Рассмотрим основные рекомендации:
Оптимизация запросов и структуры базы:
ГДЕ) и связи таблиц (СОЕДИНЕНИЕ), имеют соответствующие индексы в базе данных. Это критично для скорости выполнения запросов.СУММА, КОЛИЧЕСТВО, МАКСИМУМ, МИНИМУМ) и группировки (СГРУППИРОВАТЬ ПО) непосредственно в запросе 1С. Это позволит базе данных выполнить вычисления более эффективно, чем если бы мы делали это программно в цикле Пока Выборка.Следующий().Упрощение логики отчетов:
Консоль запросов:
Стандартная обработка "Консоль запросов" является незаменимым инструментом для разработчика 1С. Она позволяет нам быстро получать данные в виде плоских таблиц по заданным запросам и сохранять их в Excel. Это может быть очень удобно для быстрой выгрузки данных для дальнейшего анализа, когда нет необходимости в сложной структуре отчета 1С.
Если наша основная цель выгрузки — это дальнейший анализ данных в Excel, и мы сталкиваемся с тем, что отчеты из 1С приходят в неудобном для анализа формате (например, с объединенными ячейками, сложной шапкой или многоуровневой структурой), то после стандартной выгрузки (даже в формате CSV или простого Excel-файла) мы можем использовать встроенный инструмент Excel — Power Query.
Power Query позволяет нам:
Использование Power Query переносит часть логики обработки данных из 1С в Excel, что может быть удобно для бизнес-пользователей, которые хорошо владеют Excel, но не имеют доступа к конфигурированию 1С. Это позволяет им самостоятельно адаптировать данные под свои аналитические нужды, не прибегая к помощи программистов 1С. Для быстрого устранения типичных недостатков форматирования в выгруженных отчетах также подойдет надстройка для Excel с инструментами коррекции данных 1С.
Таким образом, мы видим, что задача выгрузки отчетов в Excel с разбивкой на порции может быть решена несколькими способами, от простого программного разделения табличного документа до комплексных подходов с оптимизацией производительности и постобработкой данных. Выбор конкретного метода зависит от объема данных, требований к форматированию, наличия ресурсов и целевого назначения выгружаемых файлов.