POI 讀取 Excel 文件(2003版本與2007版本的差別之處)

已整理成完整項目,並進行了優化。看參考地址: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

相關文章
相關標籤/搜索