赞
踩
场景:使用SXSSFWorkbook导出大数据量(百万行)excel报表,表格样式统一使用自适应列宽时,发现导出表头行格式异常,异常情况如下图所示:
分析:从导出效果看,应该是忽略了表头数据长度,根据数据内容的长度进行了自适应列宽调整。但是代码中自适应宽度操作是放在导出方法最后的,届时已完成表格数据渲染,理论上应该对所有表头标题数据进行自适应列宽调整。自适应列宽部分代码如下:
- //自动调整列宽
- sheet.trackAllColumnsForAutoSizing();
- for (int i = 0; i < head.size(); i++) {
- sheet.autoSizeColumn(i);
- //手动调整列宽,解决中文不能自适应问题
- //单元格单行最长支持255*256宽度(每个单元格样式已经设置自动换行,超出即换行)
- sheet.setColumnWidth(i, Math.min(255*256, sheet.getColumnWidth(i) * 12 / 10));
- }
排查:该导出功能之前经过自测,并没有发现这个问题。猜测是自测数据没有触发异常情况。遂,重新本地自测,依然无法复现。对比了自测数据和异常场景之间数据的差异,发现区别点是本地自测导出数据量比较少,只有几十行。于是加大数据量进行导出测试,问题复现。
解决:目前已知是数据量的区别,导致了自适应列宽效果异常。于是灵光一闪,想到了SXSSFWorkbook的特性。SXSSFWorkbook非常适合大数据量导出场景,因为使用之前的poi(HSSFWorkbook/XSSFWorkbook)进行大数据量导出时,会因内存不够导致OOM,而SXSSFWorkbook只在内存中加载一部分数据,其余大部分数据是加载到磁盘里面的。导致在导出大数据量的时候,表格自适应宽度只会对最后几百行的数据生效,而忽略了表头行,因此表头行的格式会异常。临时的解决方案是最后对各列的自适应宽度做一个判断,不能少于一个默认宽度大小,以免表头样式过于难看。修改后的代码如下:
- //自动调整列宽
- sheet.trackAllColumnsForAutoSizing();
- for (int i = 0; i < data.getHead().size(); i++) {
- sheet.autoSizeColumn(i);
- //手动调整列宽,解决中文不能自适应问题
- //单元格单行最长支持255*256宽度(每个单元格样式已经设置自动换行,超出即换行)
- //设置最低列宽度,列宽约六个中文字符
- int width = Math.max(15 * 256, Math.min(255 * 256, sheet.getColumnWidth(i) * 12 / 10));
- sheet.setColumnWidth(i, width);
- }
修改后的导出效果如下图所示:
总结:至此,我明白了SXSSFWorkbook也是一把双刃剑,想要正常导出大数据量的表格,必须得用它的特性,不会占大量内存,但也正是因为它的特性,在使用过程中得仔细思考潜在的问题。还有,功能测试的时候,必须考虑周密,严格按照实际情况导出测试。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。