java使用poi导出excel时,createCellStyle过多导致的异常

1. 应用场景

        项目上需要对某张数据量较大(其实也就4600多条数据,每行11列)的报表导出excel,然后发现抛出异常信息如下:

The maximum number of Cell Styles was exceeded. You can define up to 64000 style in a .xlsx Workbook

导致这个问题的直接原因,是因为在循环给sheet页的每个单元格设置样式时,使用了xssfWorkbook.createCellStyle()

2. 解决方案

        其实网上一搜一大把答案,基本都是说把createCellStyle()放到循环外面就行。所以我就照着做放到了循环外面,发现问题解决了!(真的解决了吗?其实只是伪解决)如果给某些个单元格设置一些不同的,比如背景色、字体啥的样式,那么新的问题又来了:所有的单元格样式,都会被最后设置的样式给覆盖,最后导出的excel所有单元格都是一样的了,呔!所以脑子转一转,想到了使用全局样式map保存所有不同的样式,设置样式时,先去map获取,有则使用,没有则创建后存放到map中,这样就能保证不过多的创建单元格样式了。具体看代码

2.1. 设置全局样式map

    /** 全局样式map,避免【The maximum number of Cell Styles was exceeded. You can define up to 64000 style in a .xlsx Workbook】 */
    private Map<String, XSSFCellStyle> styleMap = new HashMap<String, XSSFCellStyle>();

2.2. 获取与添加样式

XSSFCellStyle xssfCellStyle = null;
// 该属性为存放样式配置的json,请根据具体业务修改
JSONObject styleJsonObject = (JSONObject)map.get(style);
// 是否需要保存到样式map中的标识
boolean flag = false;
// 判断全局样式集合
if (this.styleMap.isEmpty()) {
    // 为空则创建
    xssfCellStyle = xssfWorkbook.createCellStyle();
    flag = true;
} else {
    // 是否已包含现有样式
    if (this.styleMap.containsKey(styleJsonObject.toString())) {
        xssfCellStyle = this.styleMap.get(styleJsonObject.toString());
    } else {
        // 获取不到则创建
        xssfCellStyle = xssfWorkbook.createCellStyle();
        flag = true;
    }
}


// ......此处省略一万行设置样式的业务代码


// 这行代码修改前使用的是cell.setCellStyle(xssfCellStyle),会引起其他异常,必须修改
cell.getCellStyle().cloneStyleFrom(xssfCellStyle);
// 如果是创建的样式,则设置完后存放到样式map中
if (flag) {
    this.styleMap.put(styleJsonObject.toString(), xssfCellStyle);
    flag = false;
}

--------------------------------------------------分割线(2022-04-19)-----------------------------------------------

cell.getCellStyle().cloneStyleFrom(xssfCellStyle);

以上这行代码,只是为了解决样式与workbook不同源的问题。设置同源后,再使用以下代码设置单元格样式就行了

cell.setCellStyle(xssfCellStyle);

--------------------------------------------------分割线(2022-05-12)-----------------------------------------------

多次测试发现以上代码存在一个bug:

因为this.styleMap为全局变量,如果同一个excel多次导出时,还是会提示非同源错误。

调整方案:

在设置样式之前,将this.styleMap重新实例化为空map

// 每次导出都初始化样式map,避免非同源错误
this.styleMap = new HashMap<String, XSSFCellStyle>();

在类中设置为全局变量时,可以直接=null,不做修改亦可。

至此,该方案为最终方案。如果看到的童鞋发现存在其他bug,欢迎评论补充,大家共同进步。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值