aliases: []
tags : " #QA #Java "
summary: [POI生成Excel超出的单元格样式的最大数量]
author : [yaenli]
notekey: [20230322-100908]

问题现象

使用Apache POI生成Excel时,如果创建的单元格样式过多,会报样式超出最大数的错误,

.xls的异常错误:

java.lang.IllegalStateException: The maximum number of cell styles was exceeded. You can define up to 4000 styles in a .xls workbook
at org.apache.poi.hssf.usermodel.HSSFWorkbook.createCellStyle(HSSFWorkbook.java:1144)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.createCellStyle(HSSFWorkbook.java:88)

.xlsx的异常错误:

java.lang.IllegalStateException: The maximum number of Cell Styles was exceeded. You can define up to 64000 style in a .xlsx Workbook
at org.apache.poi.xssf.model.StylesTable.createCellStyle(StylesTable.java:830)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.createCellStyle(XSSFWorkbook.java:750)

问题分析

同一个Workbook创建CellStyle有最大数限制,其中.xls(Excel 97) 的最大数是4000,.xlsx(Excel 2007) 的最大数是64000 。

xls 参数限制于org.apache.poi.hssf.usermodel.HSSFWorkbook :

private static final int MAX_STYLES = 4030;

public HSSFCellStyle createCellStyle() {
if (this.workbook.getNumExFormats() == MAX_STYLES) {
throw new IllegalStateException("The maximum number of cell styles was exceeded. You can define up to 4000 styles in a .xls workbook");
} ExtendedFormatRecord xfr = this.workbook.createCellXF();
short index = (short)(getNumCellStyles() - 1);
return new HSSFCellStyle(index, xfr, this);
}

xlsx 参数限制于org.apache.poi.xssf.model.StylesTable :

private static final int MAXIMUM_STYLE_ID = SpreadsheetVersion.EXCEL2007.getMaxCellStyles();// 64000

public XSSFCellStyle createCellStyle() {
if (getNumCellStyles() > MAXIMUM_STYLE_ID) {
throw new IllegalStateException("The maximum number of Cell Styles was exceeded. You can define up to " + MAXIMUM_STYLE_ID + " style in a .xlsx Workbook");
} int xfSize = this.styleXfs.size();
CTXf xf = CTXf.Factory.newInstance();
xf.setNumFmtId(0L);
xf.setFontId(0L);
xf.setFillId(0L);
xf.setBorderId(0L);
xf.setXfId(0L);
int indexXf = putCellXf(xf);
return new XSSFCellStyle(indexXf - 1, xfSize - 1, this, this.theme);
}

因此,在生成Excel时,如果同一个Workbook不停的创建CellStyle,超限时就会产生样式最大数异常,最直接的体现就是在某些代码中,对每个单元格去独立的设置样式,生成大数据量的Excel报错。

解决方案

网上最热门的解决方案是所谓的将createCellStyle 放在循环外面,这只能应付表格样式单一的情况。

由于单元格样式CellStyle 并不是单元独立拥有的,每个单元格只是保存了样式的索引,一般的Excel真正使用到的样式也不会超过4000/64000 ,因此更好的解决方案是实现单元格样式的复用(注意不同的Workbook创建的CellStyle是不能混用的)。

方案1:缓存样式实现复用

提取样式关键字作为key,将CellStyle缓存至Map:

Workbook workBook = new HSSFWorkbook();// or new XSSFWorkbook();
Sheet sheet = workBook.createSheet(strSheetName);
Map cellStyleMap = new HashMap<String, CellStyle>();// 缓存样式 // 样式代码
for (int rowIndex = 0; rowIndex < maxRow; rowIndex++) {
Row row = sheet.createRow(rowIndex);
for (int colIndex = 0; colIndex < maxCol; colIndex++) {
Cell cell = row.createCell((short) colIndex);
String styKey = getCellStyleKey(rowIndex, colIndex);// 根据获取样式key
CellStyle cellStyle = (CellStyle) cellStyleMap.computeIfAbsent(styKey, k-> workBook.createCellStyle());// 获取样式
cell.setCellStyle(cellStyle);
}
}

方案2:修改限制参数

修改POI中的限制参数( org.apache.poi.hssf.usermodel.HSSFWorkbook.MAX_STYLESorg.apache.poi.ss.SpreadsheetVersion.EXCEL2007)。

过多的创建样式会影响性能,建议仅在真正使用的样式超过限制时再去修改此参数。

方案3:延迟指定单元格样式实现复用

参见文章:

POI 操作Excel的单元格样式超过64000的异常问题解决

根据模版填充Excel并导出的工具 · GitCode

POI Excel单元格样式超过最大数(4000或64000)的解决方案的更多相关文章

  1. java POI Excel 单元格样式

    正如Html需要CSS一样,我们的POI生成的Excel同样需要样式才能更完美的表现我们的数据.下面还是从简单的例子出发,学习和了解POI的样式设计. 一.我的位置. 1 package com.my ...

  2. poi 升级至4.x 的问题总结(POI Excel 单元格内容类型判断并取值)

    POI Excel 单元格内容类型判断并取值 以前用 cell.getCachedFormulaResultType() 得到 type 升级到4后获取不到了 换为:cell.getCellType( ...

  3. POI HSSFCellStyle 设置 Excel 单元格样式

    POI中可能会用到一些需要设置EXCEL单元格格式的操作小结: 先获取工作薄对象: HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb ...

  4. POI Excel 单元格内容类型判断并取值

    个人用到的 String birthdayVal = null;                                                                     ...

  5. poi excel单元格的校验

    switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_NUMERIC://数值类型 if (0 == cell.getCellType()) { ...

  6. POI实现EXCEL单元格合并及边框样式

    POI实现EXCEL单元格合并及边框样式     下面例子为创建产生一个excel,合并单元格,然后为合并后的单元格添加边框 package test; import java.io.FileOutp ...

  7. POI解析Excel时,如何获取单元格样式以及单元格Style的一些操作

    最近,公司运营平台需要上传Excel文件并进行解析导入数据库,在开发完成后出现了一个始料不及的生产bug,下面是具体原因: 1.在用POI解析Excel时,默认如果Excel单元格中没有数据,且单元格 ...

  8. poi的各种单元格样式以及一些常用的配置

    之前我做过一个poi到处excel数据的博客,但是,后面使用起来发现,导出的数据单元格样式都不对. 很多没有居中对齐,很多单元格的格式不对,还有就是单元格的大小不对,导致数据显示异常,虽然功能可以使用 ...

  9. poi合并单元格同时导出excel

    poi合并单元格同时导出excel POI进行跨行需要用到对象HSSFSheet对象,现在就当我们程序已经定义了一个HSSFSheet对象sheet. 跨第1行第1个到第2个单元格的操作为 sheet ...

  10. POI如何自动调整Excel单元格中字体的大小

    问题 目的是要将Excel中的文字全部显示出来,可以设置对齐格式为[缩小字体填充],但是这样的话只能展示出一行数据,字体会变得很小.还有一种办法,设置对齐格式为[自动换行],然后让单元格中的字体自动调 ...

随机推荐

  1. Python的入门学习之 Day 7——from“夜曲编程”

    Day 7 time: 2021.8.4. 今天主要将"if-else"再扩展, 得到"if-elif-else"模型.它与"if-else" ...

  2. Apple Sources

    1. libsystem_malloc.dylib的源码 https://opensource.apple.com/tarballs/libmalloc/ .这里有多个版本(例如用otool找到iOS ...

  3. K8s 与 Service Mesh(服务与流量治理)

    K8s相关资料可参考链接: Kubernetes简介 1  什么是Service Mesh Service Mesh 是一个专门处理服务通讯的基础设施层.它的职责是在由云原生应用组成服务的复杂拓扑结构 ...

  4. 爱心代码_HTML

    直接上效果 <!doctype html> <html> <head> <meta charset="utf-8"> <tit ...

  5. #Python #密码管理器 无需再记住密码,使用Python实现个人密码管理器

    ​本文在CSDN"彭_Yu的博客"同步发表  目录 1.要点 2.运行原理 3.异或算法简介 4.运行效果 5.实现过程 5.1文件结构 5.2建立数据库 5.3 Python代码 ...

  6. white album句子

    1.不论是真心的笑,还是真心的生气,我都做不到.我只是个胆小的骗子.

  7. reactHooks_useEffect

    当在直接在组件内使用setState时,会产生"渲染次数过多"的错误 例如: const A = ( ) => {   const [num,setNum] = useSta ...

  8. 解决Z490-A吹雪安装macOS Monterey随机重启

    1.目前发现随机重启问题是板载网卡I225-v导致,需要去除以往的网卡的kext补丁: 2.去除补丁后发现网络连接识别成功,但是无法上网:这是因为网卡ID注入错误.需要将网卡ID设置为:F315868 ...

  9. 在uniapp中使用百度地图的Autocomplete(关键字自动完成提示)不弹出提示框的问题

    let ac = new BMap.Autocomplete({ "input": document.querySelector('input'), "location& ...

  10. springboot整合mybatis:查询语句,返回null

    springboot整合mybatis时,查询数据库数据时,返回结果为null; 刚开始以为是数据库没连接上,结果增.改.删的其他语句则执行成功: 但唯有查询语句始终返回null,一条数据一个null ...