Excel 活頁簿(xlsx)檔案格式
Office Open XML 格式的 Microsoft Excel 活頁簿。
- MIME 類型
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
- 副檔名
- .xlsx
- 分類
- 文件
Magic number(檔案簽章)
| 0x00000000 | 504B0304 | PK·· | 'PK' — it is a ZIP |
ZIP 內含 '[Content_Types].xml' 以及一個 'xl/' 目錄。
關於 Excel 活頁簿(xlsx)格式
.xlsx 是一個 Open Packaging Conventions 套件——一包 XML 元件組成的 ZIP——版面配置是為表格資料設計的。儲存格住在 xl/worksheets/sheet1.xml 之類的地方,但字串多半不住在那裡:重複的文字會被集中到 xl/sharedStrings.xml,再用索引引用,所以一份有十萬個相同標籤的活頁簿壓完幾乎不佔空間。樣式也用同樣手法集中在 xl/styles.xml。檔案開頭那幾個位元組完全看不出它是試算表;只有 ZIP 目錄裡的項目名稱看得出來。
檔頭結構,一個位元組一個位元組看
| 位移 | 長度 | 欄位 | 意義 |
|---|---|---|---|
| 0 | 4 | Local file header signature | 50 4B 03 04,ZIP 的本地檔案標頭。活頁簿、Word 文件、簡報、電子書和 Android 套件在這個位移完全無法分辨——這個格式是疊在 ZIP 之上的容器慣例,不是它自己的簽章。 |
| 4 | 2 | Version needed to extract | 最低讀取端版本乘以 10,小端序。deflate 是 20。元件超過 65535 個、或整體超過 4 GiB 的活頁簿會把它推到 45 走 ZIP64,內嵌媒體非常大的時候才會遇到。 |
| 6 | 2 | General purpose bit flag | 位元 3 會把 CRC 與大小移到壓縮資料後面的 data descriptor,串流式寫入端就是這麼做的。位元 11 宣告項目名稱是 UTF-8——這件事有意義,因為工作表元件名稱都是 ASCII,內嵌媒體的檔名卻常常不是。 |
| 8 | 2 | Compression method | 所有 XML 元件都是 8,也就是 deflate。試算表 XML 是整個 OOXML 家族裡最好壓的內容:一張全是數字儲存格的工作表,展開是一大堆囉唆的標記,deflate 之後通常剩不到十分之一。 |
| 10 | 2 | Last modified time | MS-DOS 打包的時間,解析度兩秒、沒有時區。Excel 會把元件的時間戳記正規化,所以活頁簿真正的編輯歷程在 docProps/core.xml,不在這裡。 |
| 12 | 2 | Last modified date | MS-DOS 打包的日期,從 1980 起算。值得和活頁簿自己的日期系統對照著看,後者是從 1900 起算天數(也可以選 1904)——同一個檔案裡兩個互不相干的紀元。 |
| 14 | 4 | CRC-32 | 這個元件未壓縮內容的檢查碼。Excel 載入時會驗,所以傳輸中壞掉的活頁簿會乾脆地失敗,而不是打開之後裡面的數字是錯的。 |
| 18 | 4 | Compressed size | 這個元件的 deflate 位元組數。FF FF FF FF 代表交給 ZIP64 額外欄位;大到需要 ZIP64 的活頁簿,通常在別的地方早就出問題了。 |
| 22 | 4 | Uncompressed size | 元件的原始長度。它和壓縮後大小之間的落差,正是共用字串設計獲利的地方——集中起來的那張表展開後是儲存大小的好幾倍。 |
| 26 | 2 | File name length | 第一個項目是 [Content_Types].xml 時(每個 OOXML 寫入端都這樣吐),這裡是 13 00,也就是 19 個位元組。這是第一個帶有「這檔案到底是什麼型別」資訊的欄位。 |
| 28 | 2 | Extra field length | Excel 寫出來通常是 0。被指令碼重新打包過的活頁簿常常會多出 Unix 權限或時間戳記的額外欄位,功能上沒有任何差別,但檔案的雜湊值會變。 |
| 30 | 19 | First entry name | [Content_Types].xml。它裡面有一個 Override 元素把 /xl/workbook.xml 對應到結尾是 spreadsheetml.sheet 的內容型別——那個字串就是「這個套件是活頁簿而不是文件或簡報」的權威宣告。 |
| variable | variable | xl/workbook.xml | 讓這個套件成為試算表的元件。它的位移不固定,要透過中央目錄去找。它列出每張工作表與對應的關聯 id,再經由 xl/_rels/workbook.xml.rels 解析到真正的 xl/worksheets/sheetN.xml 元件。 |
| -22 | 4 | End of central directory signature | 50 4B 05 06,沒有壓縮檔註解時位於倒數第 22 個位元組。讀取端要列出活頁簿有哪些工作表,所需的一切都是從這裡走出去的,所以最後 22 個位元組比前 30 個重要。 |
| -6 | 4 | Offset of the central directory | 目錄開始的位置,是從檔案開頭起算的絕對位置。只要在套件前面塞任何位元組,它就失效了,而 Excel 的反應是直接宣告檔案讀不了,不會去找真正的位移在哪。 |
怎麼跟長得像的格式分開
| 容易搞混的 | 怎麼分 |
|---|---|
| Word 文件(docx) | 本地檔案標頭每個欄位都一樣,位移 30 也一樣,因為兩種套件都以 [Content_Types].xml 開頭。分界在檔尾的目錄清單:活頁簿是 xl/workbook.xml 加一棵 xl/ 樹,文件是 word/document.xml 加一棵 word/ 樹。看副檔名不能代替這件事——位元組說它是什麼,Excel 就當它是什麼。 |
| xls | 它的前輩,而且是完全不同的生物:Compound File Binary 容器,開頭 D0 CF 11 E0 A1 B1 1A E1,裡面有一個叫 'Workbook' 的串流。兩者都能用 Excel 打開、都被叫做「Excel 檔」,而列與欄的上限差距極大——二進位格式是 65536 乘 256,.xlsx 是 1048576 乘 16384,這就是全世界會轉檔的實務理由。 |
| csv | 實務上常被混為一談,位元組層級則從來不會:CSV 是純文字、完全沒有簽章,.xlsx 是 ZIP。真正會咬人的是語意差異——CSV 只帶值,活頁簿帶的是值加上公式、型別、格式與多張工作表,所以「匯出成 CSV」是把檔案裡大部分東西丟掉,「用 Excel 開 CSV」則會憑空發明出原本不存在的型別。 |
| xlsm | 啟用巨集的活頁簿,標頭部分和 .xlsx 逐位元組相同,唯一的差別是多一個 xl/vbaProject.bin 元件,以及不同的 ContentType 宣告。既然看得到的差別只有副檔名、而改名不用錢,郵件過濾器要判斷這一對就非得把套件拆開看不可。 |
常見的壞法
- end-of-central-directory 記錄不見了。下載被截斷時,每個工作表元件都完好、壓縮也正確,Excel 還是拒絕開檔,因為它是從檔尾開始列舉的。從 50 4B 03 04 往後切出各個項目、重建目錄,通常每張工作表都救得回來。
- 套件前面被塞了位元組。代理伺服器的錯誤頁或一個亂入的 BOM 卡在 50 4B 03 04 前面,整個檔案就偏移了,中央目錄裡每個絕對位移都錯了同樣的量。活頁簿完整無缺;把前面的垃圾刪掉就復原了。
- 文字模式傳輸。deflate 資料流裡的換行被轉換過,標頭、項目名稱與大小全都讀得漂漂亮亮,所以套件列得出來,然後在解壓縮某張工作表時 CRC 檢查失敗。ZIP 結構在那之前完全沒有徵兆。
- 手改過的元件重新打包錯了。工作表就是純 XML,會想直接改它很正常;在 XML 宣告前面加了 BOM、改了項目名稱的大小寫、或把資料夾也加成目錄項目,任何一項都會讓 Excel 拒收——而每個壓縮工具都說這個套件很健康。
- xl/sharedStrings.xml 壞掉。儲存格文字是集中存放、用索引引用的,所以這一個元件損壞不會只讓某個儲存格變空白——它會讓整份活頁簿的字串索引全部位移,工作表打開之後,正確的數字全配上錯誤的標籤。這是這個格式最會誤導人的失效模式。
這個格式現在還在用嗎
.xlsx 套件是「稍微有點結構的表格資料」的通用交換格式,而它的覆蓋率主要是商業事實而不是技術事實:財務、營運與政府單位就是用它發布資料,所以每套資料工具都被迫要能讀。就它的定位而言,技術上算合理——開放的 ISO 標準、可壓縮、元件是 XML 所以救得回來,而且擺脫了 .xls 那個讓大型匯出根本做不了的列數上限。但拿它當資料處理格式就很糟:解析要先解壓縮、再串流讀幾 MB 的 XML;日期是以 1900 為紀元的序號存的,還刻意保留了從 Lotus 沿襲下來的閏年 bug;長的數字型識別碼會被默默轉成浮點數,再用科學記號重新格式化。任何分析導向的用途,簡單交換用 CSV、規模大就用 Parquet,兩者讀取速度都快上好幾個數量級。.xlsx 真正的首選場合,是要交給人打開、人來編輯的成品:公式、多張工作表、格式與圖表全都保得住,換成 CSV 一樣都留不下來。
在這個站上打開 Excel 活頁簿(xlsx)檔
這些全部在你的瀏覽器裡跑,檔案不會離開你的電腦。
相關格式
容易和 Excel 活頁簿(xlsx)搞混的格式,可以比對它們的開頭位元組。
| 格式 | 開頭位元組 | 副檔名 |
|---|---|---|
| Word 文件(docx) | 50 4B 03 04 | .docx |
| PowerPoint 簡報(pptx) | 50 4B 03 04 | .pptx |
| ZIP | 50 4B 03 04 | .zip |
| OLE2 / CFB | D0 CF 11 E0 A1 B1 | .doc |