模擬 SAX 解析 XML,需熟悉 BIFF8 底層 Record 結構(org.apache.poi.hssf.record)。
BOFRecord:Workbook/Sheet 開始。RowRecord:行存在及樣式信息。CellValueRecordInterface:NumberRecord、LabelSSTRecord、FormulaRecord 等表示單元格。EventRecordFactory factory = new EventRecordFactory();
factory.registerListener(new ERFListener() {
public boolean processRecord(Record rec) {
if (rec.getSid() == BOFRecord.sid) { /* 處理 BOF */ return true; }
return false;
}
}, new short[]{ BOFRecord.sid });
factory.processRecords(inputStream);
Bla.xls
├─ OLE2CDF headers
├─ "Workbook" stream
│ ├─ Workbook { Static String Table, Sheet names & pointers }
│ ├─ Sheet { ROW, ROW, NUMBER RECORD, LABELSST RECORD ... }
│ └─ Sheet ...
├─ Images, Macros (獨立流/目錄)
├─ Document Summary
└─ Summary
屬性存儲於 POIFS 專用流:\005SummaryInformation(標題、作者、創建時間等)、\005DocumentSummaryInformation(類別、多媒體剪輯數等)。
POIFSReader r = new POIFSReader();
r.registerListener(new POIFSReaderListener() {
public void processPOIFSReaderEvent(POIFSReaderEvent event) {
SummaryInformation si = (SummaryInformation) PropertySetFactory.create(event.getStream());
System.out.println("標題: " + si.getTitle());
}
}, "\005SummaryInformation");
r.read(new FileInputStream("doc.xls"));
event.getStream() 獲取屬性流。PropertySetFactory.create() 工廠轉換為 PropertySet。SummaryInformation 或 DocumentSummaryInformation 享受便捷 Getter。NoPropertySetStreamException、ClassCastException(流類型不匹配)。註冊兩個監聽器,處理時用 instanceof 或 isSummaryInformation() 區分。自定義屬性集需使用更通用的 API(參考 HPSF HOW-TO)。