DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1
讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1
編輯:XML詳解     

簡介

  創新理由編號 432:報告不利於環境。

  圖表和報告消耗樹木。電子版本使用電能和化石燃料。也許,公司能夠 “變得綠色” 並停止撰寫報告。

  為高級職員開發報告可能會讓 Java程序員感到焦慮,特別是當程序員喜歡開發人員友好的輸出(比如 XML )、但高層管理人員只講支持 GUI 的電子表格語言時。

  常用縮寫詞

  API:應用程序編程接口

  GUI:圖形用戶界面

  IDE:集成開發環境

  PNG:可移植網絡圖形

  SQL:結構化查詢語言

  XML:可擴展標記語言

  焦慮可能會增加牽涉的程序員的溫室氣體 “輸出”,特別是當他們開始喘息時。盡管報告消耗時間和資源,但是向高層管理人員提供項目可見性是很關鍵的。管理層可能會懷疑努力工作的團隊,僅僅因為高層領導看不見他們的團隊正在進行的工作。

  因此,報告對工作環境很重要。

  Java 程序員處理來自電子表格愛好者的報告時,利用幾個 Java 技巧可以提高他們的工作效率。完成本文介紹的幾個步驟之後,中級 Java 程序員應該能夠理解以編程方式在 Microsoft® Excel® 和 XML 之間轉換數據背後的基本原理。

  Excel 到 Java API

  本文使用的工具

  完成本文中的示例需要以下工具:

  XML Object Model (XOM) API 1.2.1 版

  Apache POI 3.6 版(針對 Microsoft Office 的 Java API)

 Eclipse Classic 3.5.1 版(內置 Java Platform, Standard Edition [Java SE] 版本 6 的 IDE)

  Microsoft Excel

  下面有幾個 Java API 用於操作 Excel 文件。哪個最好?這取決於您的個人需求和經驗水平。

  Andy Khan 的 Java Excel API

  Andy Khan 創建了一個稱為 Java Excel API(或 JExcel API)的 API。這個開源 API 能夠讀寫 Excel 電子表格。另外,由於它是輕量級的,因此它是初級 Java 開發人員的一個不錯選擇。這個 API 有一個方便的 UnifIEd Modeling Language (UML) 圖表和支持社區,使其簡單易用。

  這個 API 也有一些缺點。盡管能夠讀取 Microsoft Excel 95、Excel 97、Excel 2000、Excel 2002 和 Excel 2003 文件格式,但它目前不能處理較新的 Excel 格式。不能創建圖表、曲線圖和宏,而且只支持 PNG 圖像文件。

  xlSQL Excel JDBC Driver

  另一個 Excel-to-Java API 是 xlSQL Excel Java Database Connectivity (JDBC) 驅動程序,這是一個開源 API,用於將 Excel 文件當作數據庫一樣進行查詢。如果您熟悉 SQL 和 JDBC,這可能是最簡單的數據提取方法。您還可以通過使用 SQL 命令 insert 來添加數據。遺憾的是,xlSQL Excel JDBC 驅動程序目前似乎沒有得到積極支持。

  OpenXLS

  OpenXLS是名為 ExtenXLS 的商業產品 Extentech 的開源版本。OpenXLS 擁有廣泛的功能,它能以編程方式修改公式,並且使用大量格式化選項。與一些開源產品不同,它可以處理復雜對象,包括命名范圍、數據透視表、拆分框架和圖表。另外,與類似的產品相比,OpenXLS 擁有更詳盡的、關於哪些特性可用的前期文檔。遺憾的是,盡管這個開源版本支持從 97 版到 2003 版的 Excel 格式,但只有商業版本支持 Excel 2007。

apache POI

  apache POI 是一組用於處理舊版和新版 Microsoft 標准文檔的 Java API。除了支持 Excel 97 以後的版本之外,apache POI 還可以處理 Microsoft Word和 PowerPoint® 文件。您可以利用處理 Excel 文件的知識來更快地學習如何處理這些額外的文件類型。還有一個活躍的社區支持這個 API。但是,由於 apache POI 擁有如此眾多的功能且可以處理其他文件,它可能超出了只想處理 Excel 文件的開發人員需要學習的內容。

  由於 Apache POI 的支持社區和豐富功能,本文使用 apache POI。

  Java XML API

  XML 是一種流行的數據格式,有幾種方法可以在 Java 技術中處理 XML。您可以選擇最適合自己項目的任何 XML API。但是,本文使用 Elliotte Rusty Harold 的優雅 XML API:XOM。

  樣例應用程序

  本文的樣例應用程序從一個虛構的公司 Planet Power 的人力資源部門提供的一個 Excel 電子表格文件開始。這個電子表格名為 Employee_List.xls。

  本文演示如何使用 Java 技術和 apache POI 來讀取 Employee_List.xls。這個演示使用的類文件為 ExcelReader.Java,包含在一個 Eclipse 項目中。在 下載 部分下載包含樣例電子表格和 Eclipse 項目的 .zip 文件。Eclipse 項目中的一個 Readme.txt 文件解釋了 “下載” 部分中包含的其他樣例代碼。

  這個文章系列的第 2 部分將演示如何將信息轉換為 XML 並創建一個對原始數據進行了一些修改的新電子表格。

  設置

  要准備計算機以運行本文中的樣例,需完成以下步驟:

  下載 Excel 電子表格和樣例代碼。

創建目錄 C:\Planet Power 並將文件解壓到該目錄。

  使用 參考資料 部分中的鏈接下載 Eclipse。下載完成後,將它解壓到 C:\Program Files\Eclipse 目錄。

  從 參考資料 部分中的鏈接,使用 XOM 站點上的 Complete zip 鏈接下載 XOM。然後,將文件解壓到 C:\Program Files\Eclipse\lib 目錄。

  使用 參考資料 部分中的鏈接下載 apache POI。將文件解壓到 C:\Program Files\Eclipse\lib(您需要創建 lib 目錄)。

  現在已經准備好在 Eclipse 中開始工作了。

  啟動 Eclipse

  要在 Eclipse IDE 中開始工作,需完成以下步驟:

  導航到 C:\Program Files\Eclipse\eclipse 並雙擊 eclipse.exe 啟動 Eclipse。如果 Windows® 顯示一個安全警告,請單擊 Run。

  在 Workspace Launcher 窗口中,使用 C:\Eclipse_Projects 替換標為 Workspace 的路徑,然後單擊 OK。

  Eclipse 裝載完成後,單擊窗口右邊的 Workbench 圖標(參見 圖 1)。 

圖 1. Workbench 圖標
讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1 部分

  在 Package Explorer 窗格中右鍵單擊,然後單擊 Import。

  展開 General,選擇 Existing Projects into Workspace。單擊 Next(參見 圖 2)。 

圖 2. 在工作空間中導入一個現有項目
讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1 部分

 

單擊 Browse(位於 Select root directory 旁邊)並導航到 C:\Planet Power\Employees。選擇 Employees 文件夾,然後單擊 OK。

  單擊 Finish,如 圖 3 所示。 

圖 3. 將一個項目導入 Eclipse 中
讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1 部分

  Employees 文件夾現在應該出現在 Package Explorer 窗格中。

  使 XOM 和 apache POI 對 Eclipse 可用

  從技術上講,本小節中的步驟已經在導入的 Employees Eclipse 項目中執行完了。但是,如果您從頭開始自己的項目,則需要告知 Eclipse 項目使用新的 XOM 和 apache POI 下載。完成以下步驟:

  在 Package Explorer 中右鍵單擊 Employees 文件夾,然後單擊 PropertIEs。

  單擊左邊窗格中的 Java Build Path。

  單擊 LibrarIEs 選項卡。

  單擊 Add External JARs,如 圖 4 所示。 

圖 4. 添加外部 JAR 文件到構建路徑
讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1 部分

  選擇包含您將在本樣例中使用的 apache POI 部分的 Java 歸檔(JAR)文件。(如果您使用的 POI 的版本與本文相同,這個路徑將是 C:\Program Files\Eclipse\lib\poi-3.6\poi-3.6-20091214.jar)。單擊 Open。

  再次單擊 Add External JARs。

選擇包含 XOM 的 JAR 文件(如果您使用的 XOM 的版本與本文相同,這個路徑將是 C:\Program Files\Eclipse\lib\XOM\xom-1.2.1.jar)。單擊 Open。

  單擊 OK。

  使用 ExcelReader.Java 文件

  對於本文而言,使用文件 ExcelReader.Java,該文件駐留在 src\(默認包)下的 Employees 項目文件夾中。圖 5 展示了這個文件。

圖 5. 打開 Employees 項目
讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1 部分

  查看原圖(大圖)

  要運行這個文件,單擊屏幕頂部的 Run 箭頭按鈕,如 圖 6 所示。

圖 6. 運行 Java 文件
讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1 部分

  運行 ExcelReader.Java 將從 Employee_List.xls 電子表格中的單元格讀取信息,並使用 Eclipse 的 Console 選項卡顯示該信息,如 圖 7 所示。

圖 7. Eclipse 的 Console 中的 Java 輸出
讀取、回收和重用:使用 Excel、XML 和 Java 技術輕松搞定報告,第 1 部分

  查看原圖(大圖)


 

開始

  理解 Java 技術的關鍵是熟悉處理對象並實例化(即創建)那些對象的概念。創建要處理的對象的標准格式是:

class objectName = new class(); 

  objectName 是新創建的對象的名稱,它類似於一個變量,該變量標識並提供一種方法來處理那個特定對象。另外,信息(通常采用其他現有對象的形式)可能位於圓括號(class 後面的 ())中。圓括號中的信息用於創建這個新對象。

  處理文件

  每當在 Java 環境中使用文件時,都可能會遇到文件問題。例如,文件可能缺失。因此,試圖讀取一個文件可能會出錯。捕獲操作文件可能導致的任何異常。

  為了處理 Excel 文件,本文使用 FileInputStream 類(Java.io.FileInputStream)。FileInputStream 表示一個不由常規文本構成的文件。由於 Excel 文件包含二進制數據,所以這裡使用 FileInputStream 而不是 FileReader 類,後者讀取只包含文本字符的文件。

  開始編程

  讀取 Excel 工作簿的第一步是准備使用 Apache POI 和其他必要的類。ExcelReader.java 中必要的類包括一些 apache POI 類、一些異常(錯誤)類以及一些文件處理類。清單 1 展示了 ExcelReader.Java 頂端的代碼,作用是導入這些類以使它們可用。

清單 1. 導入類(ExcelReader.Java)

import Java.io.FileInputStream; 
import Java.io.IOException; 
 
import org.apache.poi.hssf.usermodel.HSSFCell; 
import org.apache.poi.hssf.usermodel.HSSFRow; 
import org.apache.poi.hssf.usermodel.HSSFSheet; 
import org.apache.poi.hssf.usermodel.HSSFWorkbook; 

  導入相關類之後,就可以開始使用 apache POI 在主方法的主體內編程了。


 

apache POI 中的 HSSF 是什麼意思?

  一些用於讀取 Excel 電子表格的類

  以下是一些用於讀取 Excel 電子表格的類:

Java.io.FileInputStream

Java.io.IOException

org.apache.poi.hssf.usermodel.HSSFWorkbook

org.apache.poi.hssf.usermodel.HSSFSheet

org.apache.poi.hssf.usermodel.HSSFRow

org.apache.poi.hssf.usermodel.HSSFCell

  apache POI API 程序員為他們的那些涉及 Excel 工作簿的類選擇了一個不尋常的命名慣例:他們使用前綴 HSSF。根據它的 JavaDocs,這個前綴實際代表 Horrible Spread Sheet Format。實際上,根據 Wikipedia,POI 最初代表 Poor Obfuscation Implementation。誰說程序員沒有幽默感?

  HSSF 類用於處理 2007 版之前的 Excel(即 .xls 文件)。另一組類 — XSSF — 用於處理 Excel 2007 或更高版本(即 .xlsx 文件)。但是,還有一組類 — SS 類 — 用於處理上述兩種版本。為簡單起見,本文使用 HSSF 類。您下載的 Eclipse 項目中的 Readme.txt 文件中指出了使用其他類的代碼樣例。

  工作簿

  在 apache POI 中表示 Excel 工作簿的 HSSF 類是 org.apache.poi.hssf.usermodel.HSSFWorkbook。將一個 FileInputStream 傳遞到 HSSFWorkbook 的構造函數中,構造函數表示 FileInputStream 所基於的文件。

  但是請等一等!在 apache POI 的 JavaDocs 中,沒有哪個 HSSFWorkbook 的構造函數表明它可以接受 FileInputStream。難道使用 FileInputStream 是一個沒有記錄在文檔中的特性?答案是否定的。的確有一個構造函數接受 InputStream。


 

由於 FileInputStream 是 InputStream 的一個子類,從技術上講,它也是一個 InputStream,因此它可以被傳遞到構造函數中。實際上,InputStream 是一個抽象類,因此某種類型的子類是必要的。因此,FileInputStream 完全可被接受。

  在實例化 FileInputStream 時,向它傳遞一個 String,用於描述要讀取的 Excel 文件的路徑。對於 Windows® 文件,轉義文件路徑中的任何特殊字符,特別是作為目錄分隔符的反斜槓(\),在文件路徑字符串中使用雙反斜槓(\\)來創建一個轉義反斜槓。

  清單 2 中的代碼實例化一個新的 FileInputStream,然後基於新 FileInputStream 實例化一個新的 HSSFworkbook。

清單 2. 讀取 Excel 文件(ExcelReader.Java)

public static void main(String[] args) { 
 // Create a FileInputStream to hold the file. 
 // Use double back-slashes to create one "escaped" slash. 
 // Use error handling (try/catch) around its creation in case 
 // the file to read does not exist. 
 // Be sure to import java.io.FileNotFoundException and Java.io.IOException, or use 
 // the superclass IOException to handle both. 
 
 try { 
  FileInputStream ExcelFIS = new FileInputStream("C:\\Planet Power\\Employee_List.xls"); 
 
  // Create an Excel Workbook Object using the FileInputStream created above 
  // (which contains the file). 
  // Use error handling around its creation in case of Input/Output Exception 
 
  HSSFWorkbook excelWB = new HSSFWorkbook(ExcelFIS); 
 
 } 
 catch (IOException e) { 
  System.out.println("Input/Output Exception!"); 
 } 
 
//End Main Method 
} 


 

現在,處於 try 錯誤處理語句中,繼續從 Excel 工作簿收集信息,我們先從它的工作表開始。

  工作表和行

  一個工作簿可以擁有幾層頁面,這些頁面稱為工作表。工作表對象由 HSSFSheet 類 org.apache.poi.hssf.usermodel.HSSFSheet 表示。

  一個工作簿有多少工作表?要找出這個信息,可以在工作簿上使用 getNumberOfSheets() 方法。但是對於本練習來說,工作簿中只有一個工作表,以便使用它的編號更簡單。第一個工作表的編號是 0(計算機喜歡從 0 而不是 1 開始計數)。代碼如 清單 3 所示。

清單 3. 獲取工作表(ExcelReader.Java)

   // Start by getting the Spreadsheet (Excel books can have several 
   // sheets). Assuming there is just one sheet, it's the zero sheet. 
 
   HSSFSheet topSheet = ExcelWB.getSheetAt(0); 

  獲取工作表對象後,遍歷工作表並處理它的數據。以下是一些有用的方法和屬性,它們的名稱表明了各自的用途。

  HSSFSheet.getFirstRowNum() 和getLastRowNum()

HSSFSheet.getHeader()
getFooter()

HSSFSheet.getRow()

HSSFSheet.getPhysicalNumberOfRows()

  要處理工作表上的數據,首先要獲取一個 HSSFRow(org.apache.poi.hssf.usermodel.HSSFRow)對象,它表示工作表中的一行。獲取一行的一種方法是在工作表上使用 getRow(),並通過行號請求一行,如 清單 4 所示。

清單 4. 獲取行(ExcelReader.Java)

   // getRow() returns an HSSFRow object, but the numbering 
   // system is logical, not physical, and zero based. 
   // for example, use getRow(2) to get the third row. 
 
   HSSFRow thirdRow = topSheet.getRow(2); 

還記得嗎,topSheet 是此前在 清單 3 中獲取的工作表。

  從工作表獲取一行後,使用該行來向下鑽取到單元格級別。

  單元格

  要挖取一個單元格的數據,使用該行來獲取一個表示該單元格的 HSSFCell 對象(org.apache.poi.hssf.usermodel.HSSFCell)。要獲取 String 格式的單元格信息,在 HSSFCell 上使用 getStringCellValue() 方法,如 清單 5 所示。

清單 5. 獲取單元格和其中的字符串(ExcelReader.Java)

   // Get the first two cells in the row 
   HSSFCell lastnameCell = thirdRow.getCell(0); 
   HSSFCell firstnameCell = thirdRow.getCell(1); 
 
   // Get the string information in the cells 
   String firstName = firstnameCell.getStringCellValue(); 
   String lastName = lastnameCell.getStringCellValue(); 
 
   // Print out the value of the cells 
   System.out.println(firstName + " " + lastName); 

  要獲取工作簿中的所有信息,只需遍歷所有工作表,每個工作表的每一行,每一行中的每個單元格。但有一個問題:嘗試運行下面的代碼,它對某些單元格有效。但是,當它試圖提取單元值並打印該值時,就會產生錯誤並退出(參見 清單 6 中的注釋)。原因何在?

清單 6. 循環所有單元格並打印值。斷開了!

// Traverse the sheets by looping through sheets, rows, and cells. 
// Remember, ExcelWB is the workbook object obtained earlIEr. 
// Outer Loop: Loop through each sheet 
 
for (int sheetNumber = 0; sheetNumber < ExcelWB.getNumberOfSheets(); sheetNumber++) { 
  HSSFSheet oneSheet = ExcelWB.getSheetAt(sheetNumber); 
 
// Now get the number of rows in the sheet 
  int rows = oneSheet.getPhysicalNumberOfRows(); 
 
  // Middle Loop: Loop through rows in the sheet 
 
  for (int rowNumber = 0; rowNumber < rows; rowNumber++) { 
   HSSFRow oneRow = oneSheet.getRow(rowNumber); 
 
   // Skip empty (null) rows. 
   if (oneRow == null) { 
     continue; 
   } 
 
   // Get the number of cells in the row 
   int cells = oneRow.getPhysicalNumberOfCells(); 
 
   // Inner Loop: Loop through each cell in the row 
 
   for (int cellNumber = 0; cellNumber < cells; cellNumber++) { 
     HSSFCell oneCell = oneRow.getCell(cellNumber); 
 
     // Get the value of the string in the cell. 
     // Print out the String value of the Cell 
     // This section will result in an error. Why? 
 
     String cellValue = oneCell.getStringCellValue(); 
     System.out.println(cellValue + ", "); 
 
   // End Inner Loop 
   } 
  // End Middle Loop 
  } 
// End Outer Loop 
} 

出了什麼問題?getStringCellValue() 方法只適用於 Strings,這也是它的名稱的由來。

  有些單元格包含數值。要避免錯誤,應測試單元格的數據類型並使用適當的方法來從該單元格提取數據類型。使用 getCellType() 來確定單元格包含的數據類型。數據的類型作為一個整數返回,該整數表示數據類型。以下靜態字段(常量)表示數據類型:

  HSSFCELL.CELL_TYPE_STRING。使用 getStringCellValue()。

  HSSFCELL.CELL_TYPE_FORMULA。使用 getCellFormula()。

  HSSFCELL.CELL_TYPE_NUMERIC。使用 getNumericCellValue()。

  HSSFCELL.CELL_TYPE_BOOLEAN。使用 getBooleanCellValue()。

  單元格也可能包含 Excel 錯誤。如果這樣,getCellType() 將返回整數 HSSFCELL.CELL_TYPE_ERROR。

  在遍歷單元格時,測試它們的數據類型,如 清單 7所示。

清單 7. 測試單元格值類型(ExcelReader.Java)

   // Inner Loop: Loop through each cell in the row 
 
   for (int cellNumber = 0; cellNumber < cells; cellNumber++) { 
     HSSFCell oneCell = oneRow.getCell(cellNumber); 
 
     // Test the value of the cell. 
     // Based on the value type, use the proper 
     // method for working with the value. 
 
     // If the cell is blank, the cell object is null, so don't 
     // try to use it. It will cause errors. 
     // Use continue to skip it and just keep going. 
 
    if (oneCell == null) { 
      continue; 
     } 
 
     switch (oneCell.getCellType()) { 
 
     case HSSFCell.CELL_TYPE_STRING: 
      System.out.println(oneCell.getStringCellValue()); 
      break; 
 
     case HSSFCell.CELL_TYPE_FORMULA: 
      System.out.println(oneCell.getCellFormula()); 
      break; 
 
     case HSSFCell.CELL_TYPE_NUMERIC: 
      System.out.println(oneCell.getNumericCellValue()); 
      break; 
 
     case HSSFCell.CELL_TYPE_ERROR: 
      System.out.println("Error!"); 
      break; 
     } 
 
   // End Inner Loop 
   } 

  當代碼運行時,注意日期顯示為數字,而不是日期,那是因為日期的格式沒有存儲在它的值中。這是單元格的一種格式化選擇。本文章系列的第 2 部分將討論如何為日期保留格式。

  還有一個重點需要注意:在 清單 7 中的以下代碼行(在下面的 清單 8 中斷開)中,這段代碼測試每個單元格,確保它們不為空。

清單 8. 不要忘記測試空值(ExcelReader.Java)

// If the cell is blank, the cell object is null, so don't 
// try to use it. It will cause errors. 
// Use continue to skip it and just keep going. 
 
if (oneCell == null) { 
  continue; 
} 

  在一個 Java 環境中,如果一個對象為空,試圖操作它將導致錯誤。在使用行和單元格這樣的對象之前,一定要測試它們,確保它們不為空。

  結束語

  具備讀取 Excel 電子表格的基本知識後,就可以開始將 Excel 數據轉換為數組、XML 或其他格式,以便執行計算或創建新的電子表格了。本文章系列的第 2 部分將演示如何將電子表格信息轉換為 XML,以及創建修改了原始數據的新電子表格。

  完成這些文章中的代碼後,確保回收它,以便實現更綠色的報告。

  本文示例源代碼或素材下載





 

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved