POI读取Excel常见问题

       最近在做一个将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

空,不知道何时算空

空就不要取值了吧

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏闵开慧

javascript入门操作

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.or...

37013
来自专栏Android知识点总结

Java总结IO之总集篇

字符流和字节流向来各行其事,很少有交集。 但Reader和Writer有两个奇子,名叫InputStreamReader(男)和OutputStreamWri...

1215
来自专栏行者悟空

基于Scala Acotor实现多线程单词统计(WordCount)

1312
来自专栏mathor

2018年全国多校算法寒假训练营练习比赛(第一场)六子冲

 棋盘上攻击方的2个棋子(2子必须相连并主动移动其中的1个)与被攻方的1个棋子皆处在一条直线上并相邻时,被攻方的这个棋子就被消灭  每次移动后判断一下,移动后...

773
来自专栏HansBug's Lab

2764: [JLOI2011]基因补全

2764: [JLOI2011]基因补全 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 570  Solv...

2948
来自专栏一个会写诗的程序员的博客

禅与 JavaScript 编程艺术, Zen and The Art of JavaScript Programming禅与 JavaScript 编程艺术

Zen and The Art of JavaScript Programming

941
来自专栏deed博客

数学速算法

1192
来自专栏小樱的经验随笔

BZOJ 1012: [JSOI2008]最大数maxnumber【线段树单点更新求最值,单调队列,多解】

1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 103...

2896
来自专栏积累沉淀

Hadoop--HDFS API编程封装

HDFS是一个分布式文件系统,既然是文件系统,就可以对其文件进行操作,比如说新建文件、删除文件、读取文件内容等操作。下面记录一下使用JAVA API对HDFS中...

26110
来自专栏扎心了老铁

java优雅的使用elasticsearch api

本文给出一种优雅的拼装elasticsearch查询的方式,可能会使得使用elasticsearch的方式变得优雅起来,使得代码结构很清晰易读。 建立elast...

7677

扫码关注云+社区