使用Apache POI讀取Excel文件

jopen 11年前發布 | 117K 次閱讀 POI Office文檔處理

摘要: 適用于Microsoft Excel xls/xlsx兩種類型電子表格的讀取操作。

        網上關于介紹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。

    Apache POI 各個包功能描述:

        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:

[ExcelReader]

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]

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]

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);
//              }
            }
        }
    }

}

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!