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. eclipse中同步git代码报错checkout conflict with files

    1.Team--->Synchronize Workspace 2.在同步窗口找到冲突文件,把自己本地修改的复制出来 3.在文件上右键选择 Overwrite----->Yes , 4.再 ...

  2. 第一课 Markdown 实操

    1.Markdown (#加空格) 二级标题 (##加空格) 三级标题 (###加空格) 四级标题 (####加空格) 2.字体 Hello world 加粗(字体2边加**) Hello world ...

  3. NIO基本编写

    一.编写server端 1 public class Server implements Runnable{ 2 //1 多路复用器(管理所有的通道) 3 private Selector selet ...

  4. linux上安装Oracle 包括常见安装错误(centos8.1,oracle linux8,redhat 8)通过

    谨记 关闭操作系统之前先关闭oracle数据库 oracle用户登录,执行lsnrctl start启动网络监听服务,执行dbstart启动数据库系统. oracle用户登录,执行lsnrctl st ...

  5. nuxt防止第三方ui多次打包

    在nuxt.config.js中的 build:{ extend(){}, verdor:['element-ui'] }

  6. 2月23日javaweb之Maven

    Maven常用命令 compile:编译 clean:清理 test:测试 package:打包 install:安装 Maven生命周期 Maven对项目构建的生命周期描述是一次构建过程经历了多少个 ...

  7. CentOS切换gcc

    centos默认的gcc版本太老了,有时候需要用新版本的gcc,编译gcc太麻烦可以使用centos提供的scl功能快速切换gcc版本 yum install centos-release-scl y ...

  8. 实现Runnable接口

    1.定义一个类用于实现Runnable接口 2.重写run()方法,编辑代码逻辑体 3.创建线程对象,调用start()开启线程 案例:我在学习 1 public class study implem ...

  9. C# NAudio 检测声音

    using NAudio.Wave;using System;using System.Collections.Generic; namespace WinFromBaidu{ class NAudi ...

  10. Linux系列---【设置ssh连接超时时间】

    设置ssh连接超时时间 shell工具总是不断的超时,上个厕所就断开了,很不方便,这里根据自己习惯设置一下. echo "export TMOUT=600" >> /e ...