已整理成完整項目,並進行了優化。看參考地址:java
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltoolsgit
咱們在作用POI讀物 Excel文件時,每每會忽略了Excel的版本,究竟是2003仍是2007。因而在讀取或寫入Excel文件時,用2003版本的Excel和用2007版本的Excel文件,會出現不兼容狀況。拋出異常,大概信息以下:org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF);github
異常指出咱們用了Office2007以上的版本(包含2007),要咱們用XSSF來代替HSSF。web
因而咱們開始替換咱們的代碼,用XSSF代替HSSF。但是咱們卻意外的發現poi.jar包中,並不包含XSSF,那麼XSSF到底從哪來的呢?百度一下發現,他們來自不一樣的星球:apache
(1)XSSFWorkbook:poi-ooxml-.jar org.apache.poi.xssf.usermodel.XSSFWorkbook
(2)HSSFWorkbook:poi.jar org.apache.poi.hssf.usermodel.HSSFWorkbookapp
查看源碼:webapp
多麼的巧合啊!HSSFWorkbook 和 XSSFWorkbook 都實現了 Workbook 接口!xss
因此思路就來了,咱們用時引入這兩種jar包,在判斷出Excel的版本號,根據Excel版本的不一樣來用HSSFWorkbook 或者XSSFWorkbook 的實現 Workbook。下面就直接上代碼吧!post
POI的版本號:優化
<poi.version>3.12</poi.version>
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>${poi.version}</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>${poi.version}</version> </dependency>
讀取Excel文件的Java類:
/** * @package :com.changhongit.andy.util<br> * @author :wanglongjie<br> * @createDate :2015年8月31日下午1:37:32<br> */ package com.changhongit.andy.util; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.poi.hssf.usermodel.HSSFDateUtil; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; /** * @package :com.changhongit.andy.util<br> * @file :ExcelReader.java<br> * @describe :讀取 Excel 文件<br> * @author :wanglongjie<br> * @createDate :2015年8月31日下午1:37:32<br> * @updater :<br> * @updateDate :<br> * @updateContent :<br> */ public class ExcelReader { static private Workbook wb; static private Sheet sheet; static private Row row; /** * * @method :readExcelTitle<br> * @describe :讀取 Excel 文件<br> * @author :wanglongjie<br> * @createDate :2015年8月31日下午2:41:25 <br> * @param fileName * :Excel 文件路徑 * @return String[] */ public static String[] readExcelTitle(String fileName) { InputStream is; try { is = new FileInputStream(fileName); String postfix = fileName.substring(fileName.lastIndexOf("."), fileName.length()); if (postfix.equals(".xls")) { // 針對 2003 Excel 文件 wb = new HSSFWorkbook(new POIFSFileSystem(is)); sheet = wb.getSheetAt(0); } else { // 針對2007 Excel 文件 wb = new XSSFWorkbook(is); sheet = wb.getSheetAt(0); } } catch (IOException e) { e.printStackTrace(); } sheet = wb.getSheetAt(0); row = sheet.getRow(0);// 獲取第一行(約定第一行是標題行) int colNum = row.getPhysicalNumberOfCells();// 獲取行的列數 String[] titles = new String[colNum]; for (int i = 0; i < titles.length; i++) { titles[i] = getCellFormatValue(row.getCell(i)); } return titles; } /** * * @method :readExcelContent<br> * @describe :讀取 Excel 內容<br> * @author :wanglongjie<br> * @createDate :2015年8月31日下午3:12:06 <br> * @param fileName * :Excel 文件路徑 * @return List<Map<String,String>> */ public static List<Map<String, String>> readExcelContent(String fileName) { List<Map<String, String>> list = new ArrayList<>(); Map<String, String> content = null; try { InputStream is; is = new FileInputStream(fileName); String postfix = fileName.substring(fileName.lastIndexOf("."), fileName.length()); if (postfix.equals(".xls")) { // 針對 2003 Excel 文件 wb = new HSSFWorkbook(new POIFSFileSystem(is)); sheet = wb.getSheetAt(0); } else { // 針對2007 Excel 文件 wb = new XSSFWorkbook(is); sheet = wb.getSheetAt(0); } } catch (IOException e) { e.printStackTrace(); } sheet = wb.getSheetAt(0); int rowNum = sheet.getLastRowNum();// 獲得總行數 row = sheet.getRow(0); int colNum = row.getPhysicalNumberOfCells(); String titles[] = readExcelTitle(fileName); // 正文內容應該從第二行開始,第一行爲表頭的標題 for (int i = 1; i <= rowNum; i++) { int j = 0; row = sheet.getRow(i); content = new LinkedHashMap<>(); do { content.put(titles[j], getCellFormatValue(row.getCell(j)) .trim()); j++; } while (j < colNum); list.add(content); } return list; } /** * 根據Cell類型設置數據 * * @param cell * @return */ private static String getCellFormatValue(Cell cell) { String cellvalue = ""; if (cell != null) { // 判斷當前Cell的Type switch (cell.getCellType()) { // 若是當前Cell的Type爲NUMERIC case Cell.CELL_TYPE_NUMERIC: case Cell.CELL_TYPE_FORMULA: { // 判斷當前的cell是否爲Date if (HSSFDateUtil.isCellDateFormatted(cell)) { // 方法2:這樣子的data格式是不帶帶時分秒的:2011-10-12 Date date = cell.getDateCellValue(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); cellvalue = sdf.format(date); } else { // 若是是純數字取得當前Cell的數值 cellvalue = String.valueOf(cell.getNumericCellValue()); } break; } // 若是當前Cell的Type爲STRIN case Cell.CELL_TYPE_STRING: // 取得當前的Cell字符串 cellvalue = cell.getRichStringCellValue().getString(); break; default: // 默認的Cell值 cellvalue = " "; } } else { cellvalue = ""; } return cellvalue; } public static void main(String[] args) { String file = "E://Andy/work/Tomcat 7.0/webapps/customer/WEB-INF/upload/客戶收支配置.xlsx"; List<Map<String, String>> list = ExcelReader.readExcelContent(file); Map<String, String> map = null; for (int i = 0; i < list.size(); i++) { map = list.get(i); Entry<String, String> entry = null; for (Iterator<Entry<String, String>> it = map.entrySet().iterator(); it .hasNext();) { entry = it.next(); System.out.println(entry.getKey() + "-->" + entry.getValue()); } System.out.println("............"); } } }
主要的思路就是,咱們在定義成員變量時不在定義某一種實現類,而是定義成接口:
static private Workbook wb;
static private Sheet sheet;
static private Row row;
而後根據上傳文件的後綴名,判斷是2003Excel仍是2007Excel,再決定用不一樣的類實現成員變量的接口,從而達到代碼既支持2003Excel有支持2007Excel:
InputStream is = new FileInputStream(fileName);
String postfix = fileName.substring(fileName.lastIndexOf("."),
fileName.length());
if (postfix.equals(".xls")) {
// 針對 2003 Excel 文件
wb = new HSSFWorkbook(new POIFSFileSystem(is));
sheet = wb.getSheetAt(0);
} else {
// 針對2007 Excel 文件
wb = new XSSFWorkbook(is);
sheet = wb.getSheetAt(0);
}
最後糾結了半天的問題終於解決了,歐耶
已整理成完整項目,並進行了優化。看參考地址:
https://gitee.com/andy_longjie/exceltools 或者 https://github.com/youmulongjie/exceltools