我在使用SXSSF导出大型.xls时出现问题,我说大的意思是27列x 10 000行。 Excel文件是端点请求返回。我的行数有限 - 可以大3倍。
我使用模板引擎插入数据。
原始代码
public StreamingOutput createStreamedExcelReport(Map<String, Object> params, String templateName, String[] columnsToHide) throws Exception {
try(InputStream is = ReportGenerator.class.getResourceAsStream(templateName)) {
assert is != null;
final Transformer transformer = PoiTransformer.createTransformer(is);
AreaBuilder areaBuilder = new XlsCommentAreaBuilder(transformer);
List<Area> xlsAreaList = areaBuilder.build();
Area xlsArea = xlsAreaList.get(0);
Context context = new PoiContext();
for(Map.Entry<String, Object> entry : params.entrySet()) {
context.putVar(entry.getKey(), entry.getValue());
}
xlsArea.applyAt(new CellRef("Sheet1!A1"), context);
xlsArea.processFormulas();
return new StreamingOutput() {
@Override
public void write(OutputStream out) throws IOException {
((PoiTransformer) transformer).getWorkbook().write(out);
}
};
}
}
SXSSF
public StreamingOutput createStreamedExcelReport(Map<String, Object> params, String templateName, String[] columnsToHide) throws Exception {
try(InputStream is = ReportGenerator.class.getResourceAsStream(templateName)) {
assert is != null;
Workbook workbook = WorkbookFactory.create(is);
final PoiTransformer transformer = PoiTransformer.createSxssfTransformer(workbook);
AreaBuilder areaBuilder = new XlsCommentAreaBuilder(transformer);
List<Area> xlsAreaList = areaBuilder.build();
Area xlsArea = xlsAreaList.get(0);
Context context = new PoiContext();
for(Map.Entry<String, Object> entry : params.entrySet()) {
context.putVar(entry.getKey(), entry.getValue());
}
xlsArea.applyAt(new CellRef("Sheet1!A1"), context);
xlsArea.processFormulas();
return new StreamingOutput() {
@Override
public void write(OutputStream out) throws IOException {
transformer.getWorkbook().write(out);
}
};
}
}
导出运行了7分钟我停止了服务器 - 它太长了。可接受的时间是1分钟(最长2分钟)。大部分时间CPU使用率约为60-80%,内存使用量不变。我也尝试输出40行 - 花了10秒钟。
也许我的功能需要优化。
其他问题是我要插入功能。在原始代码中,函数被替换为值。在SXSSF版本中,它们不是。
答案 0 :(得分:0)
我建议您在此时禁用公式处理,因为支持SXSSF版本的公式有限且内存消耗可能过高。在未来的JXLS版本中,可以改进公式支持。
所以只需删除xlsArea.processFormulas()
来电并添加
context.getConfig().setIsFormulaProcessingRequired(false);
禁用单元格引用的跟踪(如Jxls doc所示)并查看它是否有效。
另请注意,如果您使用SXSSF,模板和最终报告应采用.xlsx格式。