Задача выгрузки отчетов в формат Excel (например, выгрузка журнала регистрации в Excel) является одной из самых частых в практике программиста 1С. Однако стандартные подходы не всегда удовлетворяют требованиям производительности (что требует замера производительности и поиска узких мест), особенно когда речь идет о документах объемом в десятки тысяч строк. В этой статье мы подробно рассмотрим, как уйти от медленных алгоритмов и реализовать максимально быструю выгрузку данных.
Разберем типичную ситуацию, представленную в вопросе автора темы. Программист пытается сначала сохранить ТабличныйДокумент стандартными средствами, а затем открывает его через COMОбъект("Excel.Application"), чтобы произвести дополнительные действия. Рассмотрим этот фрагмент кода:
ЭтотОбъект.ОтчетТабличныйДокумент.Записать(ПолноеИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
ДокExcel = Новый COMОбъект("Excel.Application");
ДокExcel.Workbooks.Open(ПолноеИмяФайла);
// Дальнейшие манипуляции...
Проанализируем ситуацию: использование COM-соединения (изучите также выполнение алгоритмов через COM-подключение) само по себе является крайне ресурсоемкой операцией. При вызове Excel.Application в оперативной памяти запускается полноценный экземпляр приложения Microsoft Excel. Каждое обращение к ячейке или диапазону через точку (например, Лист.Cells(1, 1)) — это отдельный межпроцессный вызов, который занимает значительное время. Если таких вызовов тысячи, выгрузка может растянуться на десятки минут. Выясним причину: в данном случае код автора не выполняет полезной нагрузки, а лишь дублирует уже записанные данные, что делает процесс избыточным.
Самый простой и быстрый способ оптимизации — это правильное использование встроенного метода Записать() (что также ускоряет экспорт справочников в Excel). Начиная с последних версий платформы 8.3, этот метод работает достаточно оптимизировано. Рассмотрим, как минимизировать время выполнения:
// Оптимизация перед сохранением
ОтчетТабличныйДокумент.ОтображатьГруппировки = Ложь;
ОтчетТабличныйДокумент.ОтображатьСетку = Ложь;
ОтчетТабличныйДокумент.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
Если ваша задача — просто получить файл, этого метода достаточно в 90% случаев. Основная оптимизация здесь заключается в том, чтобы не использовать COM вообще, если не требуется специфическое форматирование, которое недоступно в 1С.
Если бизнес-логика требует использования именно COM-объекта (например, для вставки макросов, создания сводных таблиц или специфической защиты листов), необходимо использовать метод пакетной передачи данных. Главное правило: никогда не заполняйте ячейки в цикле.
Вместо этого мы подготовим данные в 1С в виде двумерного массива и передадим его в Excel одним вызовом. Рассмотрим этот пример:
// Создаем массив данных в 1С
МассивДанных = Новый COMSafeArray("Variant", КоличествоСтрок, КоличествоКолонок);
Для Стр = 0 По КоличествоСтрок - 1 Цикл
Для Кол = 0 По КоличествоКолонок - 1 Цикл
МассивДанных.SetValue(Стр, Кол, "Значение");
КонецЦикла;
КонецЦикла;
// Передаем весь массив сразу в диапазон Excel
ExcelДиапазон = Лист.Range(Лист.Cells(1, 1), Лист.Cells(КоличествоСтрок, КоличествоКолонок));
ExcelДиапазон.Value = МассивДанных;
Также проанализируем настройки самого приложения Excel. Чтобы ускорить процесс, обязательно отключите визуальное обновление экрана и автоматический пересчет формул на время записи:
ExcelПриложение.ScreenUpdating = Ложь;
ExcelПриложение.Calculation = -4135; // xlCalculationManual
// Процесс заполнения...
ExcelПриложение.ScreenUpdating = Истина;
ExcelПриложение.Calculation = -4105; // xlCalculationAutomatic
Для самых тяжелых отчетов (сотни тысяч строк) рассмотрим наиболее продвинутый метод — формирование файла .xlsx вручную. Напомним, что современный файл Excel — это ZIP-архив, содержащий набор XML-файлов. Мы можем генерировать эти XML-файлы напрямую через ЗаписьXML.
Разберем по шагам этот алгоритм:
_rels, docProps, xl).sharedStrings.xml, где будут храниться все уникальные строки отчета (это существенно уменьшает размер файла).sheet1.xml, описывающий ячейки.ЗаписьZipФайла и установим расширение .xlsx.Этот метод требует глубокого понимания формата Open XML, но он работает в десятки раз быстрее любого другого способа, так как полностью исключает использование тяжелых объектов ТабличныйДокумент или COM.
Рассмотрим интересный прием, упомянутый опытными разработчиками: передача данных через буфер обмена. Этот метод может показаться "хакерским", но он показывает отличные результаты по скорости на больших объемах данных.
Алгоритм действий следующий:
ТабличныйДокумент.Paste.Это позволяет платформе 1С самой оптимизировать процесс передачи данных во внешнее приложение, минуя построчный перебор ячеек.
Проанализировав ситуацию, мы можем сделать следующие выводы для оптимизации выгрузки:
Во-первых, откажитесь от использования COM-объектов, если задача решается методом ТабличныйДокумент.Записать(). Это самый стабильный и поддерживаемый путь.
Во-вторых, если вам необходимо дополнительное форматирование в Excel, используйте COMSafeArray для пакетной вставки данных. Это сократит время выгрузки с минут до секунд.
В-третьих, для сверхбольших объемов данных (биг-дата) рассмотрите возможность выгрузки в формат CSV. Это текстовый формат, который Excel открывает без проблем, а скорость его генерации в 1С максимальна, так как она выполняется простым потоком записи текста.
Выясним, какой метод подходит именно вам, исходя из объема данных: для маленьких таблиц — стандартная команда сохранения, для средних — пакетный COM, для огромных — прямая генерация XML или CSV.