最近在做一個將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 | 空,不知道何時算空 | 空就不要取值了吧 |