令人窒息的複雜度#

微軟公開了 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 二進位格式——那相當於數千年的工作量。