Apache POI занимает очень много времени, чтобы записать в рабочую книгу - PullRequest
0 голосов
/ 15 апреля 2020

Я использую Apache POI для создания и сохранения записей в Workbook . У меня есть почти 5000 + новые записи для записи и сохранения в рабочую книгу. Но во время записи fileOutputStream в рабочую книгу выполнение в основном останавливается и замедляется.

Что я хочу сказать, так это во время выполнения этой строки:

workbook.write(fileOutputStream);

он почти останавливается для обработки более 5000 записей. Я подтвердил, что на запись в рабочую книгу уходит почти 1 час (!).

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

** Примечание : остальные коды являются нормальными Apache POI связанными кодами, и они выполняются нормально, без проблем, следовательно Я не упомянул их всех. Только я застрял в приведенной выше строке.

Я нашел здесь одно обсуждение: FileOutputStream (Apachhe POI) занимает слишком много времени для сохранения

, но это не помогло меня. Мне нужно сохранить весь файл.

Ответы [ 2 ]

2 голосов
/ 15 апреля 2020

Давайте рассмотрим конкретный пример, о котором мы можем поговорить:

import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.util.GregorianCalendar;

class CreateExcel100000Rows {

 public static void main(String[] args) throws Exception {

System.out.println("whole program starts " + java.time.LocalDateTime.now());

  try (
   //Workbook workbook = new XSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xlsx")
   //Workbook workbook = new SXSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xlsx")
   Workbook workbook = new HSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xls")
   ) {

   int rows = 100000;
   if (workbook instanceof HSSFWorkbook) rows = 65536;

   Object[][] data = new Object[rows][4];
   data[0] = new Object[] {"Value", "Date", "Formatted value", "Formula"};
   for (int i = 1; i < rows; i++) {
    data[i] = new Object[] {1.23456789*i, new GregorianCalendar(2000, 0, i), 1.23456789*i, "ROUND(A" + (i+1) + ",2)"};
   }

   DataFormat dataFormat = workbook.createDataFormat();
   CellStyle dateStyle = workbook.createCellStyle();
   dateStyle.setDataFormat(dataFormat.getFormat("DDDD, MMMM, DD, YYYY"));
   CellStyle numberStyle = workbook.createCellStyle();
   numberStyle.setDataFormat(dataFormat.getFormat("#,##0.00 \" Coins\""));

   Sheet sheet = workbook.createSheet(); 

   sheet.setColumnWidth(0, 12*256);
   sheet.setColumnWidth(1, 35*256);
   sheet.setColumnWidth(2, 17*256);
   sheet.setColumnWidth(3, 10*256);

   for (int r = 0; r < data.length; r++) {
    Row row = sheet.createRow(r);
    for (int c = 0; c < data[0].length; c++) {
     Cell cell = row.createCell(c);
     if (r == 0) cell.setCellValue((String)data[r][c]);
     if (r > 0 && c == 0) {
      cell.setCellValue((Double)data[r][c]);
     } else if (r > 0 && c == 1) {
      cell.setCellValue((GregorianCalendar)data[r][c]);
      cell.setCellStyle(dateStyle);
     } else if (r > 0 && c == 2) {
      cell.setCellValue((Double)data[r][c]);
      cell.setCellStyle(numberStyle);
     } else if (r > 0 && c == 3) {
      cell.setCellFormula((String)data[r][c]);
     }
    }
   }

System.out.println("write starts " + java.time.LocalDateTime.now());
   workbook.write(fileout);
System.out.println("write ends " + java.time.LocalDateTime.now());

   if (workbook instanceof SXSSFWorkbook) ((SXSSFWorkbook)workbook).dispose();
  }

System.out.println("whole program ends " + java.time.LocalDateTime.now());

 }
}

Этот код создает HSSFWorkbook с первым листом, заполненным от строки 1 до строки 65 536, с различными типами значений ячеек в столбцах A:D.

Использование java -Xms256M -Xmx512M, то есть пространства кучи от 256 до 512 МБайт, занимает в целом 2 секунды. HSSFWorkbook.write занимает меньше секунды.

Если вы сделаете

...
  try (
   Workbook workbook = new XSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xlsx")
   //Workbook workbook = new SXSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xlsx")
   //Workbook workbook = new HSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xls")
   ) {
...

Этот код создает XSSFWorkbook с первым листом, заполненным от строки 1 до строки 100 000, с ячейками другого типа значения в столбцах A:D.

Использование java -Xms256M -Xmx512M, то есть пространства кучи от 256 до 512 МБайт, занимает в целом 7 секунд. XSSFWorkbook.write занимает 2 секунды. Это можно улучшить, предоставив больше доступного пространства кучи.

Если вы сделаете

...
  try (
   //Workbook workbook = new XSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xlsx")
   Workbook workbook = new SXSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xlsx")
   //Workbook workbook = new HSSFWorkbook(); FileOutputStream fileout = new FileOutputStream("Excel.xls")
   ) {
...

Этот код создает SXSSFWorkbook с заполнением первого листа от строки 1 до строки 100 000, имеющей различный вид значений ячеек в столбцах A:D.

При использовании java -Xms256M -Xmx512M, то есть пространства кучи от 256 до 512 МБайт, в целом это занимает 2 секунды. SXSSFWorkbook.write занимает менее секунды.

Примечание. Использование SXSSFWorkbook, ((SXSSFWorkbook)workbook).dispose() необходимо для удаления использованных временных файлов.

0 голосов
/ 17 апреля 2020

Еще одно решение, которое я понимаю, например, при переборе строки и создании ячеек НЕ продолжайте объявлять CellStyle и sheet.autoSizeColumn(colNumber) внутри l oop, скорее объявите эти 2 только один раз на внешней стороне l oop и задайте значения и стиль только внутри l oop, то есть cell.setCellStyle и cell.setCellValue.

Объявление вышеупомянутых 2 каждый раз во время итерации, в основном ухудшает производительность POI в корне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...