網頁

2012年8月23日 星期四

Read Excel(xls) with Java

這原本是客戶的需求,產出的文件希望從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(),這兩者差異,需要再仔細的研究研究。

沒有留言:

張貼留言