该文章为本系列的第三篇
第一篇为 : Java POI操作Excel(User Model)
第二篇为 : Java POI操作Excel(Event Model)
第四篇为 : 使用POI封装一个轻量级Excel解析框架
前言
原计划是写完User Model和Event Model写封装一个通用的Excel解析框架.但是这周在浏览官网查资料的时候,在FAQ里看到了Xlsx To CSV的代码.发现POI竟然还有一种解析方式叫User Event Model.
User Model & Event Model
在前面的两篇文章中,我们介绍了上述的两种解析方式.在抽象层级上面,User Model的抽象层级更好,提供了更多的API,我们不仅可以获取Cell的值,还能获取格式,获取格式化后的Cell的值.
这里需要说明一下,我们从Cell里取的值,并不一定就是我们在Excel中写入的值.如果你细心看过前面的文章你就会发现,单元格里写的19.从Cell里get出来可能是19.0。这是因为在Excel的存储中,数据和格式是分开存储的.如果你不使用这个单元格中使用的格式(DataFormatter)来解析单元格里的值,就会出现这种问题.
在User Model中由于抽象层级高,我们可以很轻易的把Cell里的值格式化成我们录入单元格的值.但是在Event Model中,就会遇到很多困难.
首先我们需要去学习Excel存储数据的各个Xml中每个标签,标签中的属性的含义,然后对解析代码进行设计,解析.有很大的学习成本.但是Event Model确实在节约内存,解析效率方面要优于User Model。
Event User Model
Event User Model = User Model + Event Model
Event User Model 解决了上述中User Model吃内存,效率相对低,而Event Model抽象程度低的问题.从整体上来看,User Event Model是采用流式解析,但是不同于Event Model,POI基于Event Model为我们封装了一层.我们不再面对Element的事件编程,而是面向StartRow,EndRow,Cell等事件编程.而提供的数据,也不再像之前是原始数据,而是全部格式化好,方便开发者开箱即用.大大简化了我们的开发效率.
xls解析
先看一个xls的Excel文件
关于Excel的设计有几个点
- 基本涵盖了业务场景下的数据类型,整数,字符串,小数,日期.
- 观察解析代码是否会解析出空格子
- 列数不等长,观察解析是否会把不够长的列,拉到和最长列一样长.
解析代码
关于代码,我们直接使用POI官网svn上的demo,对文件路径做少量修改即可.
解析结果
工作表1 [1]:
"姓名","性别","年龄","出生日期",,"防守打法"
"小明","男",19,3/12/94,,20.2,"fadsfa"
结果分析
- 所有的数据解析正常,唯一的问题就是日期的格式可能不符合我们具体的业务场景,需要后续修改
- 在行数据没有结束之前的空格子会被解析
- 每一行只会解析到最后一个有数据的单元格.在业务场景中,我们可以在解析的时候将Excel列总数传入,对行数据的尾部进行空串的补全.或者在解析成对象的代码中进行补偿.
xlsx解析
我们使用和上述的Excel相同的数据,对于解析数据的观察点也和xls的相同
解析代码
依旧使用官网提供的demo
解析结果
工作表1 [index=0]:
"姓名 xing'ming","性别 xing'bie","年龄 nian'ling","出生日期 chu'sheng ri'qi",,"防守打法 f's'd'f"
"小明 xiao'ming","男 nan",19,"3/12/94",,20.2,"fadsfa"
看到结果的你一定是懵逼的,这解析出来怎么还有拼音,甚至读不懂的字母在里面.这是Excel在存的数据中,就已经存下了这些数据(可以将xlsx的Excel压缩,在压缩包里会看到Excel存储数据的全貌),所以POI将这些数据都展示了出来.
这些数据我们仔细观察就会发现全都来自Excel的SSTable.如果你不了解什么是SSTable可以翻看前面的文章或者google.但是我们在使用User Model的时候明明不会有这些拼音数据,所以我们分析出,这部分内容应该是可选的.于是去上面的代码中找关于SSTable的代码.找到了这一行
我们点进去,发现构造函数里有第二个参数是includePhoneticRuns.在Excel真是的存储节点中,这部分拼音数据,就是在<iPh>节点下.所以我们推断把这个字段的值设置为false.即可忽略这部分的值.于是,我们修改代码,重新运行.
运行结果
工作表1 [index=0]:
"姓名","性别","年龄","出生日期",,"防守打法"
"小明","男",19,"3/12/94",,20.2,"fadsfa"
这下,我们不想要的数据已经都消失了.
这套代码的解析结果和上面的xls的解析结果是一模一样的.所以就不再次分析了.
总结
可以说发现Event User Model是一次意外,因为在网上搜索poi process excel,找到的基本都是User Model的方式,如果你搜索big Excel process.就会搜索到Event Model.更蛋疼的是,在官网的解析比较图中,也没有介绍有这种方式.
不过最终结果是好的.我们在解析Excel的路上终于有了一把更趁手的武器.节约内存,效率相对高,API对开发者友好.接下来,我们就可以基于User Model和Event User Model来实现一个通用的Excel解析框架了.