該文章為本系列的第三篇
第一篇為 : Java POI操作Excel(User Model)
第二篇為 : Java POI操作Excel(Event Model)
第四篇為 : 使用POI封裝一個輕量級Excel解析框架
前言
原計劃是寫完User Model和Event Model寫封裝一個通用的Excel解析框架.但是這周在瀏覽官網(wǎng)查資料的時候,在FAQ里看到了Xlsx To CSV的代碼.發(fā)現(xiàn)POI竟然還有一種解析方式叫User Event Model.
User Model & Event Model
在前面的兩篇文章中,我們介紹了上述的兩種解析方式.在抽象層級上面,User Model的抽象層級更好,提供了更多的API,我們不僅可以獲取Cell的值,還能獲取格式,獲取格式化后的Cell的值.
這里需要說明一下,我們從Cell里取的值,并不一定就是我們在Excel中寫入的值.如果你細心看過前面的文章你就會發(fā)現(xiàn),單元格里寫的19.從Cell里get出來可能是19.0矗晃。這是因為在Excel的存儲中,數(shù)據(jù)和格式是分開存儲的.如果你不使用這個單元格中使用的格式(DataFormatter)來解析單元格里的值,就會出現(xiàn)這種問題.
在User Model中由于抽象層級高,我們可以很輕易的把Cell里的值格式化成我們錄入單元格的值.但是在Event Model中,就會遇到很多困難.
首先我們需要去學(xué)習(xí)Excel存儲數(shù)據(jù)的各個Xml中每個標(biāo)簽,標(biāo)簽中的屬性的含義,然后對解析代碼進行設(shè)計,解析.有很大的學(xué)習(xí)成本.但是Event Model確實在節(jié)約內(nèi)存,解析效率方面要優(yōu)于User Model呼畸。
Event User Model
Event User Model = User Model + Event Model
Event User Model 解決了上述中User Model吃內(nèi)存,效率相對低,而Event Model抽象程度低的問題.從整體上來看,User Event Model是采用流式解析,但是不同于Event Model,POI基于Event Model為我們封裝了一層.我們不再面對Element的事件編程,而是面向StartRow,EndRow,Cell等事件編程.而提供的數(shù)據(jù),也不再像之前是原始數(shù)據(jù),而是全部格式化好,方便開發(fā)者開箱即用.大大簡化了我們的開發(fā)效率.
xls解析
先看一個xls的Excel文件
關(guān)于Excel的設(shè)計有幾個點
- 基本涵蓋了業(yè)務(wù)場景下的數(shù)據(jù)類型,整數(shù),字符串,小數(shù),日期.
- 觀察解析代碼是否會解析出空格子
- 列數(shù)不等長,觀察解析是否會把不夠長的列,拉到和最長列一樣長.
解析代碼
關(guān)于代碼,我們直接使用POI官網(wǎng)svn上的demo,對文件路徑做少量修改即可.
解析結(jié)果
工作表1 [1]:
"姓名","性別","年齡","出生日期",,"防守打法"
"小明","男",19,3/12/94,,20.2,"fadsfa"
結(jié)果分析
- 所有的數(shù)據(jù)解析正常,唯一的問題就是日期的格式可能不符合我們具體的業(yè)務(wù)場景,需要后續(xù)修改
- 在行數(shù)據(jù)沒有結(jié)束之前的空格子會被解析
- 每一行只會解析到最后一個有數(shù)據(jù)的單元格.在業(yè)務(wù)場景中,我們可以在解析的時候?qū)xcel列總數(shù)傳入,對行數(shù)據(jù)的尾部進行空串的補全.或者在解析成對象的代碼中進行補償.
xlsx解析
我們使用和上述的Excel相同的數(shù)據(jù),對于解析數(shù)據(jù)的觀察點也和xls的相同
解析代碼
依舊使用官網(wǎng)提供的demo
解析結(jié)果
工作表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"
看到結(jié)果的你一定是懵逼的,這解析出來怎么還有拼音,甚至讀不懂的字母在里面.這是Excel在存的數(shù)據(jù)中,就已經(jīng)存下了這些數(shù)據(jù)(可以將xlsx的Excel壓縮,在壓縮包里會看到Excel存儲數(shù)據(jù)的全貌),所以POI將這些數(shù)據(jù)都展示了出來.
這些數(shù)據(jù)我們仔細觀察就會發(fā)現(xiàn)全都來自Excel的SSTable.如果你不了解什么是SSTable可以翻看前面的文章或者google.但是我們在使用User Model的時候明明不會有這些拼音數(shù)據(jù),所以我們分析出,這部分內(nèi)容應(yīng)該是可選的.于是去上面的代碼中找關(guān)于SSTable的代碼.找到了這一行
我們點進去,發(fā)現(xiàn)構(gòu)造函數(shù)里有第二個參數(shù)是includePhoneticRuns.在Excel真是的存儲節(jié)點中,這部分拼音數(shù)據(jù),就是在<iPh>節(jié)點下.所以我們推斷把這個字段的值設(shè)置為false.即可忽略這部分的值.于是,我們修改代碼,重新運行.
運行結(jié)果
工作表1 [index=0]:
"姓名","性別","年齡","出生日期",,"防守打法"
"小明","男",19,"3/12/94",,20.2,"fadsfa"
這下,我們不想要的數(shù)據(jù)已經(jīng)都消失了.
這套代碼的解析結(jié)果和上面的xls的解析結(jié)果是一模一樣的.所以就不再次分析了.
總結(jié)
可以說發(fā)現(xiàn)Event User Model是一次意外,因為在網(wǎng)上搜索poi process excel,找到的基本都是User Model的方式,如果你搜索big Excel process.就會搜索到Event Model.更蛋疼的是,在官網(wǎng)的解析比較圖中,也沒有介紹有這種方式.
不過最終結(jié)果是好的.我們在解析Excel的路上終于有了一把更趁手的武器.節(jié)約內(nèi)存,效率相對高,API對開發(fā)者友好.接下來,我們就可以基于User Model和Event User Model來實現(xiàn)一個通用的Excel解析框架了.