从1000条记录的列表中生成apache poi excel报告,耗时超过10分钟

oxiaedzo  于 2022-12-24  发布在  Apache
关注(0)|答案(1)|浏览(191)

我用java实现了一个excel报表,使用apache-poi库,最后我有一个对象列表,有1000条记录,当我遍历这些记录并在报表中写入数据时,花费了太多的时间,我不知道这是否正常。
下面是什么和所有我有工作代码:
控制器类别:
请注意,列表report有1008条记录,最终生成报告时,需要10 minutes
当我调试时,方法writeDataLines()花费了这么多时间。

List<PricingCalculationReport> report =  pricingRuleServiceImpl.applyPricingOnAirshopReport( pricingRequest, agentId );

        log.info( "logging pricing report: " );
        log.debug( objectMapper.writeValueAsString(report) );

        if( report != null ) {
            response.setContentType("application/octet-stream");
            DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
            String currentDateTime = dateFormatter.format(new Date());

            String headerKey = "Content-Disposition";
            String headerValue = "attachment; filename=PricingReport_" + currentDateTime + ".xlsx";
            response.setHeader(headerKey, headerValue);

            PricingReporter excelExporter = new PricingReporter(report);

            excelExporter.export(response, new PricingCalculationReport());
        }

报表类,导出方式:

public void export(HttpServletResponse response, PricingCalculationReport report) throws IOException {

    try {
        writeHeaderLine( "Pricing Report", report );
        writeDataLines();

        ServletOutputStream outputStream = response.getOutputStream();
        workbook.write(outputStream);
        workbook.close();

        outputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

}

报表类,writeDataLines方法:

private void writeDataLines() throws Exception {
    int rowCount = 2;

    CellStyle style = workbook.createCellStyle();
    XSSFFont font = workbook.createFont();
    font.setFontHeight(10);
    style.setFont(font);

    for (PricingCalculationReport report : objects) {
        Row row = sheet.createRow(rowCount++);
        int columnCount = 0;

        createCell(row, columnCount++, report.getOfferId(), style);
        createCell(row, columnCount++, report.getOfferItemId(), style);
        createCell(row, columnCount++, report.getRuleName(), style);
        createCell(row, columnCount++, report.getFareType().name(), style);
        createCell(row, columnCount++, report.getAdjustmentType().name(), style);
        createCell(row, columnCount++, report.getAdjustmentValue(), style);
        createCell(row, columnCount++, report.getIsVisible(), style);
        createCell(row, columnCount++, report.getOfferItemBaseAmount(), style);
        createCell(row, columnCount++, report.getOfferItemTaxAmount(), style);
        createCell(row, columnCount++, report.getOfferItemTotalAmount(), style);
        createCell(row, columnCount++, report.getNewOfferItemBaseAmount(), style);
        createCell(row, columnCount++, report.getNewOfferItemTotalAmount(), style);
        createCell(row, columnCount++, report.getOfferBaseAmount(), style);
        createCell(row, columnCount++, report.getOfferTaxAmount(), style);
        createCell(row, columnCount++, report.getOfferTotalAmount(), style);
        createCell(row, columnCount++, report.getNewOfferBaseAmount(), style);
        createCell(row, columnCount++, report.getNewOfferTotalAmount(), style);
        createCell(row, columnCount++, report.getOfferItemMarkupCalculated(), style);
        createCell(row, columnCount++, report.getOfferMarkupCalculated(), style);

    }
}

创建单元格方法:

private void createCell(Row row, int columnCount, Object value, CellStyle style) {
    sheet.autoSizeColumn(columnCount);
    Cell cell = row.createCell(columnCount);
    if (value instanceof Integer) {
        cell.setCellValue((Integer) value);
    } else if (value instanceof Double) {
        cell.setCellValue((Double) value);
    } else if (value instanceof Boolean) {
        cell.setCellValue((Boolean) value);
    } else if (value instanceof BigDecimal) {
        cell.setCellValue( ((BigDecimal) value).doubleValue()  );
    } else {
        cell.setCellValue((String) value);
    }
    cell.setCellStyle(style);
}

报告者类别:

public class PricingReporter {

   private XSSFWorkbook workbook;
   private XSSFSheet sheet;
   private List<PricingCalculationReport> objects;

   public PricingReporter(List<PricingCalculationReport> objects) {
       this.objects = objects;
       workbook = new XSSFWorkbook();
   }
}

谢谢你的建议。

vh0rcniy

vh0rcniy1#

我想这些方法直接编写一个打开的Excel工作表。请注意,Excel在获得控制权时需要相当多的时间,特别是在涉及到单元格格式或列大小时,您将控制权传递给Excel cca 20 K次。然而,Excel中的批量操作实际上并不会花费更多的时间。根据我在VBA中的经验,关键是减少应用程序-Excel通过对Range个单元格(列、行、矩形,甚至是Union个不连续的区域)应用操作来进行交换。
因此,如果您有1008行相同的格式,那么您可以从第一行收集一次样式,用粗略的数据填充工作表,并在最后逐列应用格式。
您也可以考虑关闭Excel的自动格式化服务,看到这一速度加快。

相关问题