使用POI中XSSF 实现“合并单元格时,仅保留左上角单元格的值,而放弃其他的值“ 问题排查笔记
一、背景介绍
在项目中借助POI 和 JXLS 两个开源工具jar实现excel数据导出,原有使用POI->HSSF方式进行数据导出,随着导出数据量的增大远远超出单sheet 65535条上限,将导出方式由POI->HSSF升级为POI->XSSF方式。
术语说明:
JXLS:国外常用数据模版导出工具,easyPOI 是国内常用数据模版导出工具,
POI->HSSF方式:支持Excel 97-2007版本的文件导出,单个sheet页最多能到导出65535条记录
POI->XSSF方式:支持Excel2007以上版本的文件导出,单个sheet无条数限制
二、核心代码
maven jar包依赖
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.15</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.15</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schema</artifactId><version>3.15</version>
</dependency>
<dependency><groupId>net.sf.jxls</groupId><artifactId>jxls-core</artifactId><version>1.0.6</version>
</dependency>
HSSF方式:
import net.sf.jxls.transformer.XLSTransformer;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
try{//JXLS文件模版地址 文件配置详参:http://jxls.sourceforge.net/getting_started.htmlString outFilePath ="xxxx/file.xls";//数据集合Map<String, Object> dataMap = new HashMap<>();//数据赋值 略dataMap.put("users",new ArrayList<>());//加载JXLS文件模版InputStream fileStream = new FileInputStream(new File(outFilePath));//对JXLS文件模版 进行数据赋值,数据来源有XLSTransformer transformer = new XLSTransformer();HSSFWorkbook workbook = (HSSFWorkbook) transformer.transformXLS(fileStream, dataMap);//获取 excel 文件的第一个sheet页HSSFSheet sheet = workbook.getSheetAt(0);// 合并单元格操作 详参:https://poi.apache.org/apidocs/4.0/// 将第一个sheet页中的 第4列 第1行到16行进行单元格合并(行和列从0开始)sheet.addMergedRegion(new CellRangeAddress(1, 17, 3, 3));// 数据文件导出到指定目录 简化FileOutputStream fout = new FileOutputStream("xxxx/exportData.xls");workbook.write(fout);fout.close();
}catch (Throwable e){//......
}
XSSF方式:
import net.sf.jxls.transformer.XLSTransformer;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
try{//JXLS文件模版地址 文件配置详参:http://jxls.sourceforge.net/getting_started.htmlString outFilePath ="xxxx/file.xlsx";//.....同上XSSFWorkbook workbook = (XSSFWorkbook) transformer.transformXLS(fileStream, dataMap);//获取 excel 文件的第一个sheet页XSSFSheet sheet = workbook.getSheetAt(0);// 合并单元格操作 详参:https://poi.apache.org/apidocs/4.0/// 将第一个sheet页中的 第4列 第1行到16行进行单元格合并(行和列从0开始)sheet.addMergedRegion(new CellRangeAddress(1, 17, 3, 3));// 数据文件导出到指定目录 简化FileOutputStream fout = new FileOutputStream("xxxx/exportData.xlsx");workbook.write(fout);fout.close();
}catch (Throwable e){//......
}
三、XSSF问题说明
正主来了,升级为POI->XSSF方式后,发现生成的excel文件,合并单元格列如下所示:
发现合并后的列中的值并未清空,导致excel默认计数和求和数值不正确。经排查发现,因为POI->XSSF中进行addMergedRegion 合并单元格时并不支持“合并单元格时,仅保留左上角单元格的值,而放弃其他的值”。在excel2007版本在进行合并单元格时会默认提示如下所示:
排查了到POI 的4.1.0 版本为止,都不存在合并单元格时保留仅保留坐上角值的相关配置,于是技术上搞不定的事只能通过业务手段搞定,与业务沟通后退求其次,允许excel默认计数值错误,保证excel默认求和正确,具体操作方式如下所示:
try{//.....同上略XSSFWorkbook workbook = (XSSFWorkbook) transformer.transformXLS(fileStream, dataMap);//获取 excel 文件的第一个sheet页XSSFSheet sheet = workbook.getSheetAt(0);//将2到16行 第3列的值设置为0 for(int i=2;i<17;i++){sheet.getRow(i).getCell(3).setCellValue(0);}//.....同上略
}catch (Throwable e){//......
}
最终通过手动将需合并的1~16行中第3列,保留第1行第3列的值,将第2行到第6行的第3列的值设置为0的方式保证导出的excel文件中默认求和数据的正确性。
四、XSSF问题说明
1.IllegalArgumentException: Merged region A4 must contain 2 or more cells
原因:由于CellRangeAddress 四个参数配置错误,计算公式为 (_lastRow - _firstRow + 1)*(_lastCol - _firstCol + 1)<2 ,通过计算公式算出可合并的行数小于2,说明没有可合并的列或行导致报错
2.org.apache.poi.openxml4j.exceptions.OLE2NotOfficeXmlFileException: The supplied data appears to be in the OLE2 Format. You are calling the part of POI that deals with OOXML (Office Open XML) Documents. You need to call a different part of POI to process this data (eg HSSF instead of XSSF)
原因:在使用POI->XSSF时,使用的FileInputStream 模版文件格式为file.xls导致问题产生,将模版另存为.xlsx
使用POI中XSSF 实现“合并单元格时,仅保留左上角单元格的值,而放弃其他的值“ 问题排查笔记相关推荐
- easypoi 如何合并相同的列,如何在Java中的POI中使用XWPFTable合并单元格(或应用colspan)?...
Creating a table in poi was quite easy but it has very limited tutorials and I cannot find one that ...
- android excel合并单元格,合并单元格的同时保留所有数值
作者:Excel Home 来源:<Excel实战技巧精粹> 发表于:2008年9月26日 合并单元格是用户在制作表格时常用的命令,它可以把多个单元格显示成一个单元格,起到美化的作用. 通 ...
- html怎么把excel表格合并单元格,巧用格式刷实现Excel合并后保留原单元格数据
合并单元格是用户在制作表格时常用的命令,它可以把多个单元格显示成一个单元格,起到美化的作用. 通常情况下,如果把几个含有数据的单元格进行合并,Excel会提示"在合并单元格时,如果选择的单元 ...
- POI中设置Excel单元格格式样式(居中,字体,边框,背景色、列宽、合并单元格等)
HSSFSheet sheet = workbook.createSheet("sheet1");//新建sheet页 HSSFCellStyle cellStyle = wb.c ...
- 使用poi来导入具有合并单元格的excel表格
pom依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml< ...
- POI中设置Excel单元格格式
POI中可能会用到一些需要设置EXCEL单元格格式的操作小结: 先获取工作薄对象: HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb ...
- java poi导出excel,合并单元格
java导出excel一般都是2种情况,一种是依赖一个实体类进行导出,或者把数据查询出来当成一个视图,对视图进行创建实体:另一种方式就是通过数据还要计算,然后一块统计,那么就不是很好处理了,我采用的是 ...
- POI进行Excel的合并单元格数据处理
POI进行Excel的合并单元格数据处理 近日接到一个要处理合并Excel单元格的上料表的需求,就到网上找了一些模板,发现有的技术大牛还是挺厉害的,对他们致以敬意. 合并单元格工具类 在这个类中将传入 ...
- 使用POI创建word表格合并单元格兼容wps
poi创建word表格合并单元格代码如下: /** * @Description: 跨列合并 */ public void mergeCellsHorizontal(XWPFTable table, ...
- POI操作行列、合并单元格、解决单元格边框缺少问题
POI-操作行列单元格 一.POI-操作行 1.1 场景:直接插入行 1.2 场景:先移动旧行 再插入新行 1.3 单元格样式的设置 二.POI-操作列 三.POI-合并单元格 一.POI-操作行 ...
最新文章
- C#面向集合的扩展(讨论)
- 程序江湖:第十四章 离开让男人成长
- Android GridView的使用方法
- 寻找最大的K个数,Top K问题的堆实现
- 什么是野指针和内存泄露?如何避免野指针
- 解决《Mobile绘制背景图片》中的问题
- GRPC在网页前端的使用
- 用java编写一个图书管理系统_手把手教你编写第一个java程序
- leetcode - 63. 不同路径 II
- Jquery监听value的变化
- java数字转换成大写字母
- 解决spring-data-jpa 级联添加时,主表放弃对外键维护时外键字段为null
- 技术帖:如何把mobi文件转化成pdf
- 经典机器学习模型:朴素贝叶斯分类
- python大气模型算法_[学习笔记][Python机器学习:预测分析核心算法][利用Python集成方法工具包构建梯度提升模型]...
- 假如让你从 0 到 1 实现一个直播弹幕系统
- STUN和TURN技术浅析
- 工作后能捡起英语的三个网站
- STM32(C语言)内存分布
- 解决win10/Office2016/Onedrive/上载中心经常冲突的问题
热门文章
- ContentRoot 和 WebRoot 的区别
- 世界上5种顶级思维,你一定要知道
- C语言---编译器、编辑器
- win10打开计算机出现马赛克,传授win10系统在线播放视频出现马赛克的技巧
- 如何在阿里云服务器部署程序并用域名直接访问
- Java中的求和公式_Sympy codegen:求和索引函数
- 如何实现阿里云服务器数据迁移?
- 8. 求 s=a+aa+aaa+aaaa+aa…a 的值
- html怎么改表格背景,javascript修改表格背景色实例代码分享
- 为帮助建筑和设施管理者满足保持社交距离的需求,Bentley 软件公司开放对 LEGION Simulator 和 OpenBuildings Station Designer 的完全访问权限,并在