继上一篇性能爆炸!SXSSFWorkbook原文件上追加写入&分页导出_sxssfworkbook 模板写入-CSDN博客
那篇其实还没有完全爆炸,但为啥不删除那一篇呢,因为那篇也算是一种思路。这篇文章是属于另外一种思路的玩法。上一篇是读取一个已有的excel再进行追加写,但实际过程中我们分页查询时都是在一个for中进行实现的,所以压根没必要搞那么复杂,复制然后转模式进行写。
先给一段代码,里面注释是保姆级教学了。
String filePath ="";//你的文件路径
FileOutputStream outputStream = null;
//内存缓存1024行
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(1024);
SXSSFSheet sxssfSheet = sxssfWorkbook.createSheet("Sheet1");
//样式,最好在循环外创建
CellStyle cellStyle = sxssfWorkbook.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.RIGHT);
cellStyle.setWrapText(true);
//这里每个export实现不同业务,清晰一点,而不在业务代码中追加表头和数据
ReportChannelSellExport export = new ReportChannelSellExport();
//创建表头
export.bulidTitle(sxssfSheet);
try {
//先把流给开起来,这样不要每次for写完关闭又打开,就for完才关
outputStream = new FileOutputStream(filePath);
for (int i = 0; i < batches; i++) {
//这里是分批次逻辑
int offset = i * splitValue;
input.setLimit(splitValue);
input.setOffset(offset);
input.setIsPage(true);
//分页查询
DataResult<List<ChannelSellReportOrderDTO>> sellReportDataResult = buyVoucherOrderFacade.querySellReportOrder(input);
DataResult.checkSucc(sellReportDataResult);
List<ChannelSellReportOrderDTO> sellReportList = sellReportDataResult.getData();
//此处------------------------分割线--------------
export.setExportList(sellReportList);
//这里是写数据的开始行,因为标题已经占了第0行 所以+1
int tmp = offset+1;
//数据开始行
for (List<String> objectList : export.bulidData()) {
Row row = sxssfSheet.createRow(tmp++);
for (int j =0;j<objectList.size();j++) {
Cell cell = row.createCell(j);
cell.setCellStyle(cellStyle);
if (objectList.get(j) == null) {
cell.setCellValue("");
} else {
cell.setCellValue(objectList.get(j));
}
}
}
//sheet先刷新到硬盘
sxssfSheet.flushRows();
}
//写入数据,注意在for外
sxssfWorkbook.write(outputStream);
outputStream.flush();
} catch (IOException e) {
log.error("分页导出异常", e);
new File(filePath).delete();
throw new ErrorCodeException(OpenApiSvcError.FILE_SAVE_ERROR, "分页导出异常");
}finally {
//记得关流,不是try-with-resources模式不会自动关闭资源
try {
sxssfWorkbook.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
以上代码谁用谁爽,不过有一个点需要注意的,这个我也搞了蛮久。就是不要想着一个for就调用write方法写一次,这个思路看上去是没错。但你执行会第一个for之后,再调用
Row row = sxssfSheet.createRow(tmp++);
就会报错了,报java.lang.RuntimeException: java.io.IOException: Stream closed at org.apache.poi.xssf.streaming.SXSSFSheet.createRow(SXSSFSheet.java:148) ~[poi-ooxml-4.0.1.jar:4.0.1]
这时你就会疑惑,我都没自己关闭过流,怎么流就没了呢。
根源在于以下这个方法,会自己关闭_out对象。
sxssfWorkbook.write(outputStream);
最后就是对比测试下性能,搞点大数据量测测吧。问题都不大。
、