POI读取Excel常见问题

本文讨论了在将Excel数据导入报表时使用POI遇到的问题,包括数值类型处理、日期类型处理及数据有效性的局限,并提出了解决方案。重点介绍了如何优化数值和日期类型的转换,以及如何处理数据有效性问题,最终考虑转向OpenXML作为更优选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       最近在做一个将excel导入到报表中的功能,使用了POI来实现,发现POI使用有诸多不便之处,先记录下来,以后可能考虑使用Openxml。

       1. 数值类型处理

       通过POI取出的数值默认都是double,即使excel单元格中存的是1,取出来的值也是1.0,这就造成了一些问题,如果数据库字段是int,那么就会wrong data type,所以需要对数值类型处理。

Cell cell = null;// 单元格
Object inputValue = null;// 单元格值
if (!isEmpty(cell) && cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
	long longVal = Math.round(cell.getNumericCellValue());
	if (Double.parseDouble(longVal + ".0") == doubleVal)
		inputValue = longVal;
	else
		inputValue = doubleVal;
}
       这么处理后,单元格中的小数没有变化,如果是整数,也会取到整数。

       2. 日期类型处理

       很遗憾,POI对单元格日期处理很弱,没有针对的类型,日期类型取出来的也是一个double值,所以同样作为数值类型。

Cell cell = null;// 单元格
Object inputValue = null;// 单元格值
if (!isEmpty(cell) && cell.getCellType() == Cell.CELL_TYPE_NUMERIC) {
    if (DateUtil.isCellDateFormatted(c))// 判断单元格是否属于日期格式
	    inputValue = cell.getDateCellValue();//java.util.Date类型
}

       可以判断得到的Date是日期时间、日期还是时间,可以通过cell.getCellStyle().getDataFormat()来判断,这个返回值没有一个常量值来对应,我本机是excel2013,测试结果是日期时间(yyyy-MM-dd HH:mm:ss) - 22,日期(yyyy-MM-dd) - 14,时间(HH:mm:ss) - 21,年月(yyyy-MM) - 17,时分(HH:mm) - 20,月日(MM-dd) - 58,有了这个,可以根据数据库字段类型,处理之后再入库,相当不方便。

       另外,如果单元格数据格式是自定义的日期格式,那么通过DateUtil.isCellDateFormatted(cell)判断不出来,而且该单元格还是一个数值单元格,返回一个double值,这里比较2。针对这种方式,有两种解决方案,第一种,重写DateUtil.isCellDateFormatted(cell)方法,开源的都有源码;第二种,cell.getCellStyle().getDataFormatString()来判断,这个方法会返回格式字符串,通过这个字符串去匹配,再处理。

       3. 数据有效性

       很奇怪,POI能生成数据有效性(下拉列表),却得不到,或者说我没找到方法去得到,蛋疼。

       附单元格数据类型:

常量说明取值
Cell.CELL_TYPE_NUMERIC数值类型cell.getNumericCellValue()
或cell.getDateCellValue()
Cell.CELL_TYPE_STRING字符串类型cell.getStringCellValue()
或cell.toString()
Cell.CELL_TYPE_BOOLEAN布尔类型cell.getBooleanCellValue()
Cell.CELL_TYPE_FORMULA表达式类型cell.getCellFormula()
Cell.CELL_TYPE_ERROR异常类型
不知道何时算异常
cell.getErrorCellValue()
Cell.CELL_TYPE_BLANK空,不知道何时算空空就不要取值了吧
  

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值