使用Apache POI讀取Excel文件

        網上關於介紹Apache POI操做Excel的文章已經不少了,但都講得比較複雜。poi的API 與實際使用中的Excel很相似,能夠說是POI把Excel中的workbook、sheet、cell等對象化了,在實際使用中極易理解。但因爲Apache POI在存在已有不短期,至少在excel2007以前就已經出現,形成一樣一套Api並不能同時讀取(寫入)xls和xlsx兩種類型的Excel文件。但poi對excel有一個很好的抽象(ss包下的Workbook、Sheet、Cell等類),能夠必定程度上忽略xls/xlsx的處理細節,針對其通用部分進行處理,但若是須要對各自有理強的支持,仍是建議使用相應的API。 java

    Apache POI 各個包功能描述: c++

        HSSF - 提供讀寫Microsoft Excel XLS格式檔案的功能。
        XSSF - 提供讀寫Microsoft Excel OOXML XLSX格式檔案的功能。
        HWPF - 提供讀寫Microsoft Word DOC格式檔案的功能。
        HSLF - 提供讀寫Microsoft PowerPoint格式檔案的功能。
        HDGF - 提供讀Microsoft Visio格式檔案的功能。
        HPBF - 提供讀Microsoft Publisher格式檔案的功能。
        HSMF - 提供讀Microsoft Outlook格式檔案的功能。

 

下面給出一個簡單的實現Demo: apache

[ExcelReader] app

package net.yeah.likun_zhang.excel;

import static net.yeah.likun_zhang.util.Debug.printf;

import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import net.yeah.likun_zhang.util.Debug;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
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;

/**
 * 讀取Excel 97~2003 xls格式 /2007~ xlsx格式
 * @author		ZhangLiKun
 * @mail		likun_zhang@yeah.net
 * @date		2013-5-11
 */
public class ExcelReader {

	/**
	 * 建立工做簿對象
	 * @param filePath
	 * @return
	 * @throws IOException
	 * @date	2013-5-11
	 */
	public static final Workbook createWb(String filePath) throws IOException {
		if(StringUtils.isBlank(filePath)) {
			throw new IllegalArgumentException("參數錯誤!!!") ;
		}
		if(filePath.trim().toLowerCase().endsWith("xls")) {
			return new HSSFWorkbook(new FileInputStream(filePath)) ;
		} else if(filePath.trim().toLowerCase().endsWith("xlsx")) {
			return new XSSFWorkbook(new FileInputStream(filePath)) ;
		} else {
			throw new IllegalArgumentException("不支持除:xls/xlsx之外的文件格式!!!") ;
		}
	}
	
	public static final Sheet getSheet(Workbook wb ,String sheetName) {
		return wb.getSheet(sheetName) ;
	}
	
	public static final Sheet getSheet(Workbook wb ,int index) {
		return wb.getSheetAt(index) ;
	}
	
	public static final List<Object[]> listFromSheet(Sheet sheet) {
		
		int rowTotal = sheet.getPhysicalNumberOfRows() ;
		Debug.printf("{}共有{}行記錄!" ,sheet.getSheetName() ,rowTotal) ;
		
		List<Object[]> list = new ArrayList<Object[]>() ;
		for(int r = sheet.getFirstRowNum() ; r <= sheet.getLastRowNum() ; r ++) {
			Row row = sheet.getRow(r) ;
			if(row == null)continue ;
			// 不能用row.getPhysicalNumberOfCells(),可能會有空cell致使索引溢出
			// 使用row.getLastCellNum()至少能夠保證索引不溢出,但會有不少Null值,若是使用集合的話,就不說了
			Object[] cells = new Object[row.getLastCellNum()] ;	
			for(int c = row.getFirstCellNum() ; c <= row.getLastCellNum() ; c++) {
				Cell cell = row.getCell(c) ;
				if(cell == null)continue ;
				cells[c] = getValueFromCell(cell) ;
			}
			list.add(cells) ;
		}
		
		return list ;
	}
	
	
	/**
	 * 獲取單元格內文本信息
	 * @param cell
	 * @return
	 * @date	2013-5-8
	 */
	public static final String getValueFromCell(Cell cell) {
		if(cell == null) {
			printf("Cell is null !!!") ;
			return null ;
		}
		String value = null ;
		switch(cell.getCellType()) {
			case Cell.CELL_TYPE_NUMERIC :	// 數字
				if(HSSFDateUtil.isCellDateFormatted(cell)) {		// 若是是日期類型
					value = new SimpleDateFormat(DatePattern.LOCALE_ZH_DATE.getValue()).format(cell.getDateCellValue()) ;
				} else 	value = String.valueOf(cell.getNumericCellValue()) ;
				break ;
			case Cell.CELL_TYPE_STRING:		// 字符串
				value = cell.getStringCellValue() ;
				break ;
			case Cell.CELL_TYPE_FORMULA:	// 公式
				// 用數字方式獲取公式結果,根據值判斷是否爲日期類型
				double numericValue = cell.getNumericCellValue() ;
				if(HSSFDateUtil.isValidExcelDate(numericValue)) {	// 若是是日期類型
					value = new SimpleDateFormat(DatePattern.LOCALE_ZH_DATE.getValue()).format(cell.getDateCellValue()) ;
				} else 	value = String.valueOf(numericValue) ;
				break ;
			case Cell.CELL_TYPE_BLANK:				// 空白
				value = ExcelConstants.EMPTY_CELL_VALUE ;
				break ;
			case Cell.CELL_TYPE_BOOLEAN:			// Boolean
				value = String.valueOf(cell.getBooleanCellValue()) ;
				break ;
			case Cell.CELL_TYPE_ERROR:				// Error,返回錯誤碼
				value = String.valueOf(cell.getErrorCellValue()) ;
				break ;
			default:value = StringUtils.EMPTY ;break ;
		}
		// 使用[]記錄座標
		return value + "["+cell.getRowIndex()+","+cell.getColumnIndex()+"]" ;
	}	
	
}

 測試類[ExcelReaderTest] xss

package net.yeah.likun_zhang.excel;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

import net.yeah.likun_zhang.BaseTest;
import net.yeah.likun_zhang.util.Debug;
import net.yeah.likun_zhang.util.ToString;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.junit.Test;

/**
 * 讀取
 * @author		ZhangLiKun
 * @mail		likun_zhang@yeah.net
 * @date		2013-5-8
 */
public class ExcelReaderTest extends BaseTest{

	@Test
	public void testRead() throws FileNotFoundException, IOException {
		Workbook wb = ExcelReader.createWb("src/main/resources/excels/demo-3.xlsx") ;
		
		// 獲取Workbook中Sheet個數
		int sheetTotal = wb.getNumberOfSheets() ;
		Debug.printf("工做簿中的工做表個數爲:{}" ,sheetTotal);
		
		// 獲取Sheet
		Sheet sheet = ExcelReader.getSheet(wb, 0) ;
		
		// 遍歷Sheet
		List<Object[]> list = ExcelReader.listFromSheet(sheet) ;
		Debug.printf(list, new ToString<Object[]>(){
			private int index = 1 ; 
			@Override
			public String toString(Object[] t) {
				
				if(t == null || t.length == 0)return StringUtils.EMPTY ;
				StringBuffer sb = new StringBuffer(index ++ + ":") ;
				for(int i = 0 ,len = t.length ; i < len ; i++) {
					sb.append(t[i] + ",") ;
				}
				return sb.toString();
			}
		}) ;
		
	}
	
}

測試輔助類[Debug] ide

package net.yeah.likun_zhang.util;

import java.util.Collection;
import java.util.Iterator;

import org.apache.commons.lang3.ArrayUtils;

/**
 * Debug函數庫
 * @author		ZhangLiKun
 * @mail		likun_zhang@yeah.net
 * @date		2013-5-8
 */
public class Debug {

	/**
	 * 打印函數
	 * @param objects
	 * @date	2013-5-8
	 */
	public static final void printf(String msg ,Object ...objects) {
		if(ArrayUtils.isEmpty(objects)) {
			System.out.println(msg);
			return ;
		}
		for(int i = 0 ,len = objects.length ; i < len ; i ++) {
			Object obj = objects[i] ;
			msg = msg.replaceFirst("\\{\\}", obj == null ? "" : obj.toString()) ;
		}
		System.out.println(msg);
	}
	
	/**
	 * 打印函數
	 * @param obj
	 * @date	2013-5-8
	 */
	public static final void printf(Object obj) {
		if(obj != null){
			System.out.println(obj.toString());
		}
	}	
	
	/**
	 * 打印集合
	 * @param list
	 * @param ts
	 * @date	2013-5-8
	 */
	public static final <T> void printf(Collection<T> list ,ToString<T> ts) {
		if(list == null || list.isEmpty()) return ;
		Iterator<T> iter = list.iterator() ;
		while(iter.hasNext()) {
			T t = iter.next() ;
//			if(t == null)continue ;
			if(ts == null) {
				System.out.println(t.toString());
			} else {
				String msg = ts.toString(t) ;
//				if(msg != null) {
					System.out.println(msg);
//				}
			}
		}
	}
	
}

 

Demo完,以上僅爲我的愚見,其中謬誤之處請你們不吝指出。 函數

相關文章
相關標籤/搜索