解决java poi之SXSSFWorkbook导出大数据量时自适应列宽效果异常问题

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 21:00   2304   0

场景:使用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也是一把双刃剑,想要正常导出大数据量的表格,必须得用它的特性,不会占大量内存,但也正是因为它的特性,在使用过程中得仔细思考潜在的问题。还有,功能测试的时候,必须考虑周密,严格按照实际情况导出测试。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP