令人窒息的複雜度#
微軟公開了 Office 二進位檔案格式的規格說明書,結果令人震驚:光是 Excel 97-2003 的格式就需要 349 頁 PDF 來描述。而且說明書中還特別註明:「每一個 Excel 工作簿都儲存在一個複合文件中」——這意味著單個檔案裡其實包含了一整個階層式檔案系統(hierarchical file system)。
普通程式員看到這些規格說明書,通常會得出以下(錯誤的)結論:
- 故意搞這麼複雜,不想讓人看懂
- 設計者是瘋狂的 Borg
- 不可能讀懂它們,也不可能做出正確的產品
這些結論全都錯了。Office 檔案格式的複雜性有其深刻的歷史與技術原因。
為什麼是二進位格式?#
二進位格式的設計目標與 HTML 等文字格式完全不同:
- 速度優先:早期 Excel 需要在 20MHz 的 80386 機器上流暢運行,記憶體只有約 1MB
- 磁碟直接映射記憶體:讀取一筆記錄就是從磁碟「快速傳送」幾個位元組到一個 C 語言結構體,無需任何詞法分析(lexing)或解析(parsing)
- 特殊的儲存優化:如 Excel 的「Simple Save」和 Word 的「Fast Save」,讓保存長文件從 30 秒縮短到 1 秒
歷史包袱的累積#
- 沒有考慮互通性(interoperability):設計者假設 Word 格式只會被 Word 讀寫,不需要與其他軟體交換資料
- 必須反映應用程式的全部複雜性:Word 的每一個複選框、每一個格式選項,都必須在檔案格式中有對應的表示
- 向後相容的代價:為了相容舊版本,過時的功能依然保留在格式中,不會額外增加微軟的成本,但想完整解析就必須處理這些歷史遺跡
以 Excel 為例,工作表有兩種日期元年:1900 年 1 月 1 日(為了與 Lotus 1-2-3 相容,還包含一個閏年計算錯誤)和 1904 年 1 月 1 日(來自 Mac 版本)。要正確處理日期,你必須同時支援兩種格式。
實用的變通做法#
對於大多數應用場景,直接讀寫 Office 二進位格式是錯誤的選擇。Joel 提供了兩種替代方案:
方案一:讓 Office 為你幹髒活
- 透過 COM Automation 呼叫 Word/Excel 的完整物件模型
- 適用場景:Word 轉 PDF、操作 Excel 工作簿、填寫 Word 表格等
- 可在 IIS 環境中用 ASP/ASP.NET 呼叫,甚至可以透過負載平衡擴展
方案二:使用更簡單的檔案格式
- 純表格資料 → CSV 格式
- 需要計算功能 → WK1 格式(Lotus 1-2-3 格式,比 Excel 格式簡單得多)
- Word 文件 → HTML 格式 或 RTF 格式(非二進位,可直接編輯修改)
- 必須用 Excel 特有格式 → 找一個老版本(如 Excel 3.0),生成最小化的檔案
除非你真的想寫一個能與 Office 競爭的軟體,否則不要嘗試完整實作 Office 二進位格式——那相當於數千年的工作量。