POI事件模式读取Excel 2003文件
一.概述
1.?Excel 2003文件(即后綴為xls)是二進制文件,存儲結構為復合文檔,POI讀取xls文件有兩種方式
2. 事件模式適用于愿意學習一點低級API結構的中間開發人員。它使用起來相對簡單,但需要對Excel文件j結構有個基本了解。
二. 存儲格式
2.1 Workbook document
1.Excel 2003文件稱之為一個Workbook文檔(Workbook document),一個Workbook document包含一個全局設置(Workbook globals)和至少一個Sheet
2.2 文檔流Workbook Stream
Excel 2003文檔(Workbook document)是以復合文檔的格式存儲,復合文檔的原理就像一個文件系統,Excel整個文件對應的流文件稱為“ Workbook Stream”,Workbook stream又被分成了許多子流(Substream)2.3 子流SubStreams
文件流是按順序存儲的:三. 目錄結構Directory
從上面我們知道以復合文檔為存儲格式的Excel 2003文件是以各種單獨的子流SubStreams,各種子流SubStreams安按照一定的順序構成整個文檔流Workbook Stream. 那我們解析Excel 2003文件時怎么進入各種子流SubStream呢? 這就要靠目錄結構Directory了:3.1 目錄條目按序列舉
3.2 目錄條目結構
目錄Directory將每個倉庫Storage的直接成員(倉庫或流)放在一個獨立的紅黑樹中
四. 記錄Record
Excel 2003文件中各種子流SubStreams會被解析為各種記錄Record,每種Record包含文檔中各種內容或特定的數據- BOFRecord : 記錄了Workbook或一個sheet的開始
- EOFRecord : 記錄了Workbook或一個sheet的結尾
- STRecord : 記錄了Excel中所有文件大院個的文本值
- .......
4.1 Record解析順序
五. Workbook解析步驟
5.1 BOFRecord / EOFRecord
1.位置:org.apache.poi.hssf.record.BOFRecord、org.apache.poi.hssf.record.EOFRecord
2.BOFRecord表示Workbook或一個sheet的開始,EOFRecord表示Workbook或一個sheet的結尾
3.如圖:
5.2 FormatRecord
1. 位置: org.apache.poi.hssf.record.FormatRecord 2.?FormatRecord表示一個單元格樣式,每個單元格樣式對應一個索引和單元格字符串 3. 如圖:5.3?ExtendedFormatRecord
1. 位置: org.apache.poi.hssf.record.ExtendedFormatRecord 2.?ExtendedFormatRecord記錄了一個單元格的屬性5.4?BoundSheetRecord
1. 位置:org.apache.poi.hssf.record.BoundSheetRecord 2.?BoundSheetRecord記錄了一個Sheet的名稱:5.5 SSTRecord
1.位置:org.apache.poi.hssf.record.SSTRecord
2.SSTRecord中存儲了在Excel中文本單元格中的文本值,文本單元格通過索引獲取文本值
3.如圖
六. WorkSheet解析步驟
6.1 BOFRecord/EOFRecord
1.? org.apache.poi.hssf.record.BOFRecord 2. type=16表示開始解析WorkSheet 3. 如圖:6.2 DimensionsRecord
1.位置:org.apache.poi.hssf.record.DimensionsRecord
2.DimensionsRecord存儲了一個sheet的行列范圍
| field_1_first_row | sheet中第一有效行行號 |
| field_2_last_row | sheet中最后有效行行號+1 |
| field_3_first_col | sheet中第一有效列列號 |
| field_4_last_col | sheet中最后有效列列號+1 |
3.如圖
6.3 ColumnInfoRecord
1.位置:org.apache.poi.hssf.record.ColumnInfoRecord
2.ColumnInfoRecord存儲了sheet中一列的信息
3.如圖:
6.4 RowRecord
1.? 位置: org.apache.poi.hssf.record.RowRecord 2. RowRecord記錄了當前行行信息:6.5?LabelSSTRecord
1. 位置:org.apache.poi.hssf.record.LabelSSTRecord
2. LabelSSTRecord記錄了一個sheet中的文本單元格
3. 如圖:
| NumberRecord | 數值單元格 |
| LabelSSTRecord | 引用了SSTRecord中一個String類型的單元格值 |
| BoolErrRecord | 布爾或錯誤單元格,根據屬性isError判斷是布爾還是錯誤單元格 |
| FormulaRecord | 公式單元格 |
| BlankRecord | 空白單元格,單元格沒有值,但是有單元格樣式 |
| StringRecord | 存儲文本公式的緩存結果 |
| LabelRecord | 只讀,支持讀取直接存儲在單元格中的字符串,而不是存儲在SSTRecord中,除了讀取不要使用LabelRecord,應該使用SSTRecord替代 |
6.6?NumberRecord
1.? 位置:? org.apache.poi.hssf.record.NumberRecord 2. NumberRecord記錄了一個Sheet中的數值單元格:數值或日期 3. 如圖:6.7?BoolErrRecord
1. 位置:?? org.apache.poi.hssf.record.BoolErrRecord 2.?BoolErrRecord記錄了一個Sheet中布爾單元格或錯誤單元格 3. 如圖:6.8?FormulaRecord
1. 位置:? org.apache.poi.hssf.record.FormulaRecord 2.?FormulaRecord記錄了一個Sheet中的公式單元格 3. 如圖:6.9?BlankRecord
1. 位置:? org.apache.poi.hssf.record.BlankRecord 2. BlankRecord記錄了一個Sheet中一個空單元格:即單元格中沒有值,但是單元格有單元格樣式 3. 如圖:6.10 MergeCellsRecord
1.? 位置:? org.apache.poi.hssf.record.MergeCellsRecord 2.?MergeCellsRecord記錄了一個Sheet中一個合并單元格 3. 如圖:七. 解析步驟
使用POI事件模式解析Excel 2003文件,需要先將Excel 2003文件轉化為POI中POIFSFileSystem對象7.1 設置監聽的Record
Excel XLS文檔最終被解析為一個個Record,如果某些Record設置了監聽器,會觸發監聽器事件 解析Excel XLS數據通常需要設置下面這些Record的監聽器: BOFRecord.sid, // HSSFWorkbook、HSSFSheet的開始 EOFRecord.sid, // HSSFWorkbook、HSSFSheet的結束 BoundSheetRecord.sid, // BoundSheetRecord記錄了sheetName SSTRecord.sid, // SSTRecord記錄了所有Sheet的文本單元格的文本 DimensionsRecord.sid, // DimensionsRecord記錄了每個Sheet的有效起始結束行列索引 MergeCellsRecord.sid, // MergeCellsRecord記錄了每個Sheet中的合并單元格信息 ExtendedFormatRecord.sid, // ExtendedFormatRecord記錄了擴展的單元格樣式 FormatRecord.sid, // FormatRecord記錄單元格樣式信息 ColumnInfoRecord.sid, // ColumnInfoRecord記錄了Sheet中列信息,如列是否隱藏 RowRecord.sid, // RowRecord記錄了Sheet中行信息,如行索引,行是否隱藏 BlankRecord.sid, // Sheet中空單元格,存在單元格樣式 BoolErrRecord.sid, // Sheet中布爾或錯誤單元格 FormulaRecord.sid, // Sheet中公式單元格 LabelSSTRecord.sid, // Sheet中文本單元格 NumberRecord.sid // Sheet中數值單元格:數字單元格和日期單元格7.2 org.apache.poi.poifs.filesystem.POIFSFileSystem類
7.3 org.apache.poi.hssf.eventusermodel.HSSFListener
HSSFListener是與HSSFRequest和HSSFEventFactory一起使用的接口- 用戶應該實現接口HSSFListener,創建一個自己的監聽器類Workbook
- listener可以注冊到HSSFRequest實例request中,用于監聽特定的Record
- 一個Record可以設置多個監聽器,處理不同的事
7.4 org.apache.poi.hssf.eventusermodel.HSSFRequest
HSSFRequest中有一個Map,用于存儲所有特定Record的監聽器,一個Record可以設置多個監聽器| addListener(HSSFListener lsnr, short sid) | 為sid的記錄record注冊一個監聽器lsnr |
| addListenerForAllRecords(HSSFListener lsnr) | 為org.apache.poi.hssf.record.Record包中所有的記錄注冊一個監聽器lsnr 不推薦用這種方法,影響性能 |
| processRecord(Record rec) | 由HSSFEventFactory調用,處理記錄rec 記錄rec可能注冊了多個監聽器,循環觸發每個注冊的監聽器,處理記錄record |
7.5 org.apache.poi.hssf.eventusermodel.HSSFEventFactory
根據POIFSFileSystem實例解析Excel XLS文件的類| processWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) | 將一個文件處理為基本的Record事件 @param req 一個HSSFRequest實例,記錄了Record的所有監聽器 @param fs 包含WorkBook的POIFS文件系統 |
| processWorkbookEvents(HSSFRequest req, DirectoryNode dir) | 將一個文件處理為基本的Record事件 @param req 一個HSSFRequest實例,記錄了Record的所有監聽器 @param dir 包含WorkBook的DirectoryNode |
| processEvents(HSSFRequest req, InputStream in) | 將一個文件處理為基本的Record事件 @param req 一個HSSFRequest實例,記錄了Record的所有監聽器 @param in?包含WorkBook的DirectoryNode的輸入流 |
| short abortableProcessWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) | 將一個文件處理為基本的Record事件 返回數值,如果監聽器是繼承AbortableHSSFListener,返回值不為0,則不會觸發當前記錄的其他監聽器, 就會繼續處理下一個記錄 |
| short abortableProcessWorkbookEvents(HSSFRequest req, DirectoryNode dir) | 將一個文件處理為基本的Record事件 返回數值,如果監聽器是繼承AbortableHSSFListener,返回值不為0,則不會觸發當前記錄的其他監聽器, 就會繼續處理下一個記錄 |
| short abortableProcessEvents(HSSFRequest req, InputStream in) | 將一個文件處理為基本的Record事件 返回數值,如果監聽器是繼承AbortableHSSFListener,返回值不為0,則不會觸發當前記錄的其他監聽器, 就會繼續處理下一個記錄 |
八.一個事件模式實例
8.1 HSSFListener接口的實現類
package poi.hssf.event; import org.apache.poi.hssf.eventusermodel.HSSFListener; import org.apache.poi.hssf.record.BOFRecord; import org.apache.poi.hssf.record.BoundSheetRecord; import org.apache.poi.hssf.record.LabelSSTRecord; import org.apache.poi.hssf.record.NumberRecord; import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.RowRecord; import org.apache.poi.hssf.record.SSTRecord; public class HSSFListenerImpl implements HSSFListener {private SSTRecord sstrec;/*** This method listens for incoming records and handles them as required.* @param record The record that was found while reading.*/public void processRecord(Record record) {switch (record.getSid()) {// the BOFRecord can represent either the beginning of a sheet or the workbookcase BOFRecord.sid:BOFRecord bof = (BOFRecord) record;if (bof.getType() == BOFRecord.TYPE_WORKBOOK) {System.out.println("處理 workbook");// assigned to the class level member} else if (bof.getType() == BOFRecord.TYPE_WORKSHEET) {System.out.println("處理sheet");}break;case BoundSheetRecord.sid:BoundSheetRecord bsr = (BoundSheetRecord) record;System.out.println("New sheet named: " + bsr.getSheetname());break;case RowRecord.sid:RowRecord rowrec = (RowRecord) record;System.out.println("Row found, first column at "+ rowrec.getFirstCol() + " last column at " + rowrec.getLastCol());break;case NumberRecord.sid:NumberRecord numrec = (NumberRecord) record;System.out.println("Cell found with value " + numrec.getValue()+ " at row " + numrec.getRow() + " and column " + numrec.getColumn());break;// SSTRecords store a array of unique strings used in Excel.case SSTRecord.sid:sstrec = (SSTRecord) record;for (int k = 0; k < sstrec.getNumUniqueStrings(); k++) {System.out.println("String table value " + k + " = " + sstrec.getString(k));}break;case LabelSSTRecord.sid:LabelSSTRecord lrec = (LabelSSTRecord) record;System.out.println("String cell found with value "+ sstrec.getString(lrec.getSSTIndex()));break;}} }
8.2 Test
packagepoi.hssf.event; importjava.io.FileInputStream; importjava.io.IOException; importjava.io.InputStream; importorg.apache.poi.hssf.eventusermodel.HSSFEventFactory; importorg.apache.poi.hssf.eventusermodel.HSSFRequest; importorg.apache.poi.poifs.filesystem.POIFSFileSystem; publicclass TestEventAPI {publicstatic void main(String[] args) throwsIOException {FileInputStream fin = newFileInputStream("C:\\Users\\Administrator\\Desktop\\測試.xls");try{POIFSFileSystem poifs = newPOIFSFileSystem(fin);try{// 從流中獲取Excel的WorkBook流InputStream workBookInputStream = poifs.createDocumentInputStream("Workbook");try{HSSFRequest hssfRequest = newHSSFRequest();// 為所有的record注冊一個監聽器hssfRequest.addListenerForAllRecords(newHSSFListenerImpl());// 創建事件工廠HSSFEventFactory factory = newHSSFEventFactory();// 根據WorkBook輸入流處理所有事件factory.processEvents(hssfRequest, workBookInputStream);}finally{workBookInputStream.close();}}finally{poifs.close();}}finally{// 一旦所有的監聽器處理完成,關閉文件輸入流fin.close();}} }總結
以上是生活随笔為你收集整理的POI事件模式读取Excel 2003文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS 开发AVFoundation系统
- 下一篇: 总结——》【养生之道】