API для написания огромных файлов Excel с помощью Java
-
18-09-2019 - |
Вопрос
Я хочу написать в файл Excel (.xls MS Excel 2003 Format) программатически с использованием Java. Выходные файлы Excel могут содержать ~ 200 000 строк, которые я планирую разделить по количеству листов (64K строк на лист, из -за предела Excel).
Я пытался использовать API APACHE POI, но, кажется, это свинья памяти из -за модели объекта API. Я вынужден добавлять ячейки/листы в объект рабочей книги в памяти, и только после добавления всех данных я могу написать книгу в файл! Вот образец того, как Apache рекомендует писать файлы Excel, используя их API:
Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("new sheet");
//Create a row and put some cells in it
Row row = sheet.createRow((short)0);
// Create a cell and put a value in it.
Cell cell = row.createCell(0);
cell.setCellValue(1);
// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
Очевидно, что написание рядов ~ 20 тыс. (С около 10-20 столбцов в каждом ряду) дает мне страшное «java.lang.outofmemoryerror: java huep space».
Я попытался увеличить начальный размер HEAPSIZE и максимальный размер кучи, используя параметры XMS и XMX в виде XMS512M и XMX1024. Все еще не могу написать в файл более 150 тысяч строк.
Я ищу способ транспортировки в файл Excel вместо того, чтобы построить весь файл в памяти, прежде чем записать его на диск, который, как мы надеемся, сохранит много использования памяти. Любой альтернативный API или решения будет оценен, но я ограничен использованием Java. Спасибо! :)
Решение
Все существующие Java API пытаются создать весь документ в RAM одновременно. Попробуйте написать файл XML, который соответствует новому формату файла XSLX. Чтобы начать вас, я предлагаю построить небольшой файл в желаемой форме в Excel и сохранить его. Затем откройте ее и изучите структуру и замените нужные детали.
Википедия имеет Хорошая статья об общем формате.
Другие советы
Попробуй использовать SXSSF Рабочая тетрадь, это здорово для огромных документов XLS, его строительного документа и вообще не ешьте ОЗУ, потому что используя NIO
Мне пришлось разделить свои файлы на несколько файлов Excel, чтобы преодолеть исключение пространства кучи. Я подумал, что около 5 тыс. Руков с 22 столбцами было об этом, поэтому я только что сделал свою логику, чтобы каждые 5 -километровые строки я заканчивал файл, запустил новый и просто сместил файлы соответственно.
В тех случаях, когда у меня было написано 20K + строки, у меня было бы 4+ разных файлов, представляющих данные.
Взглянуть на HSSF Serializer от проекта Cocoon.
Serializer HSSF ловит события SAX и создает электронную таблицу в формате XLS, используемом Microsoft Excel
Также есть Jexcelapi, но он использует больше памяти. Я думаю, что вы должны создать файл .csv и открыть его в Excel. Это позволяет вам передавать много данных, но вы не сможете выполнить «магию Excel».
Рассмотрим использование формата CSV. Таким образом, вы больше не ограничены памятью -ну, может быть, только во время предварительной пропалирования данных для CSV, но это также можно сделать эффективно, например, запросы подмножества строк из DB, например, например, LIMIT/OFFSET
и немедленно напишите его в файл вместо того, чтобы перевозить все содержимое таблицы DB в память Java, прежде чем написать любую строку. Ограничение Excel суммы строк в одном «листе» увеличится примерно до одного миллиона.
Тем не менее, если данные на самом деле поступают из БД, то я бы очень пересмотрел, если Java является правильным инструментом для этого. Большинство приличных БД имеют функцию экспорта в CSV, которая может выполнить эту задачу, несомненно, намного более эффективной. В случае, например, MySQL, вы можете использовать LOAD DATA INFILE
командовать для этого.
Мы разработали библиотеку Java для этой цели, и в настоящее время она доступна в качестве проекта с открытым исходным кодом https://github.com/jbaliuka/x4j-analytic Анкет Мы используем его для оперативной отчетности. Мы генерируем огромные файлы Excel, ~ 200 000 должны работать без проблем, Excel также удается открывать такие файлы. Наш код использует POI для загрузки шаблона, но сгенерированный содержимое транслируется непосредственно в файл без XML или уровня модели объекта в памяти.
Происходит ли эта проблема с памятью, когда вы вставляете данные в ячейку или когда вы выполняете вычисление данных/генерацию?
Если вы собираетесь загрузить файлы в Excel, состоящий из предварительно определенного формата статического шаблона, то лучше сохранить шаблон и повторно использовать несколько раз. Обычно шаблоны случаются, когда вы собираетесь генерировать ежедневный отчет о продажах и т. Д.
Иначе, каждый раз, когда вам нужно создавать новую строку, границу, столбец и т. Д. С нуля.
Пока что Apache Poi - единственный выбор, который я нашел.
«Очевидно, что написание рядов ~ 20 тыс. (С около 10-20 столбцов в каждом ряду) дает мне страшное« java.lang.outofmemoryerror: пространство из кучи Java ».
"Enterprise It"
То, что вы можете сделать,- это выполнить вставку пакетов данных. Создайте таблицу Queuetask, каждый раз после генерации 1 -й страницы, отдыхайте на секунды, затем продолжайте вторую часть. Если вы беспокоитесь о динамических изменениях данных во время задачи очереди, вы можете сначала получить первичный ключ в Excel (скрывая и заблокируя столбец из представления пользователя). Сначала запуск будет вставить первичный ключ, а затем запуск второй очередь будет зачитываться из блокнота и выполнять часть задачи по участке.
Мы сделали что -то довольно похожее, одинаковое количество данных, и нам пришлось переключиться на Jexcelapi, потому что POI настолько тяжелый в ресурсах. Попробуйте jexcelapi, вы не пожалеете об этом, когда вам придется манипулировать большими изделиями!