這原本是客戶的需求,產出的文件希望從pdf改成excel,雖然最後需求被否決了,還是花了點時間了解一下,避免到時回馬槍,殺得措手不及。

沒想到用 java 還蠻幸福的,Apache 提供了一組 API 來操作微軟的文件,所以相關的 jar 檔和文件都可以在 官網 Apache POI - the Java API for Microsoft Documents 找到,這時最新版本是3.8。

接下來就來小小的測試一下:
仔細看了文件,不同的 excel 版本所需的 API 不同,Office 2007(+) 包含了 xml ,至於之前的版本使用OLE2,因此提供不同的 API 來處理不同版本的文件。

事前準備:Book1.xls 文件(即2007以前的版本),內容如下:


從官網下載下來那一整包裡面包含一堆jar檔,這次範例只用到poi-3.8-20120326.jar,記得將它加到CLASSPATH裡面。

如果沒有用IDE之類的編輯器,可以像我一樣,使用bat file,做些設定就可以編輯測試,這樣就不用每次測試個小程式,還要搬出每隻大怪獸。
build.bat 內容如下(請改成你自己使用的相關目錄):
@echo off
set JAVA_HOME=C:\Program Files\Java\jdk1.5.0_14
set PATH=%PATH%;%JAVA_HOME%\bin
set CLASSPATH=.;%JAVA_HOME%\lib;%JAVA_HOME%\jre\lib;D:\Study\java\apache\poi-3.8\poi-3.8-20120326.jar
echo ***** Compile %1.java Start *****
javac %1.java pause

run.bat 內容如下(請改成你自己使用的相關目錄):
@echo off
set JAVA_HOME=C:\Program Files\Java\jdk1.5.0_14
set PATH=%PATH%;%JAVA_HOME%\bin
set CLASSPATH=.;%JAVA_HOME%\lib;%JAVA_HOME%\jre\lib;D:\Study\java\apache\poi-3.8\poi-3.8-20120326.jar
echo ***** Run %1 Start *****
java %1

ReadXls.java
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
public class ReadXls {
    public static void main(String[] args) {
        try {
            POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("Book1.xls"));
            HSSFWorkbook wb = new HSSFWorkbook(fs);
            HSSFSheet sheet = wb.getSheetAt(0);
            System.out.println("LRM="+sheet.getLastRowNum());
            System.out.println("PNOR="+sheet.getPhysicalNumberOfRows());
            for (int idx=0; idx<sheet.getLastRowNum(); idx++) {
                HSSFRow row = sheet.getRow(idx);
                System.out.println( String.format("%s\t%s\t%s\t", row.getCell(0).toString(), row.getCell(1).toString(), row.getCell(2).toString() ) );
            }

            System.out.println("============================================");
            for (int idx=0; idx<sheet.getPhysicalNumberOfRows(); idx++) {
                HSSFRow row = sheet.getRow(idx);
                System.out.println( String.format("%s\t%s\t%s\t", row.getCell(0).toString(), row.getCell(1).toString(), row.getCell(2).toString() ) );
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

編譯:
D:\Study\java\apache\poi-3.8\test>build.bat ReadXls
***** Compile ReadXls.java Start *****
請按任意鍵繼續 . . .

執行及結果:
D:\Study\java\apache\poi-3.8\test>run.bat
ReadXls ***** Run ReadXls Start *****
LRM=3
PNOR=4
日期 姓名 電子信箱
21-八月-2012 Apple apple@test.com
19-八月-2012 Bill bill@test.com
============================================
日期 姓名 電子信箱
21-八月-2012 Apple apple@test.com
19-八月-2012 Bill bill@test.com
18-八月-2012 Cat cat@test.com

後記:
無意間發現了API在取得Row個數時,提供了不同的method,getLastRowNum()和getPhysicalNumberOfRows(),這兩者差異,需要再仔細的研究研究。

, ,

mark528 發表在 痞客邦 PIXNET 留言(0) 人氣()