ByteScope

Excel ブック(xlsx)ファイル形式

Office Open XML 形式の Microsoft Excel ブック。

MIME タイプ
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
拡張子
.xlsx
カテゴリ
ドキュメント

マジックナンバー(ファイル署名)

0x00000000504B0304PK··'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 にプールされ、インデックスで参照されます。同じラベルが 10 万行並んだブックがほぼ無に等しいサイズまで縮むのはこの仕組みのおかげです。スタイルも同じように xl/styles.xml にプールされます。ファイルの先頭バイトにはこれが表計算であることを示すものは何もなく、判別できるのは ZIP ディレクトリのエントリ名だけです。

ヘッダーの構造(バイト単位)

オフセット長さフィールド意味
04Local file header signature50 4B 03 04、ZIP のローカルファイルヘッダです。ブックも Word 文書もスライドも電子書籍も Android パッケージも、このオフセットでは区別が付きません。この形式は独自の署名ではなく、ZIP の上に載せたコンテナの取り決めだからです。
42Version needed to extract必要な読み取り側の最小バージョンを 10 倍した値、リトルエンディアン。deflate なら 20 です。パーツが 65535 個を超えるブックや 4 GiB を超えるブックは ZIP64 の 45 になりますが、それが起きるのは巨大なメディアを埋め込んだときくらいです。
62General purpose bit flagビット 3 は CRC とサイズを圧縮データの後ろの data descriptor へ移します。ストリーミングで書く実装の挙動です。ビット 11 はエントリ名が UTF-8 であることを宣言します。ワークシートのパーツ名は ASCII でも、埋め込みメディアのファイル名はそうとは限らないので、これは意味を持ちます。
82Compression methodXML パーツはすべて 8(deflate)。表計算の XML は OOXML 一族の中で最もよく縮む中身で、数値セルのシートは冗長なマークアップが平然と 10 分の 1 以下になります。
102Last modified timeMS-DOS のパック形式の時刻で、分解能 2 秒、タイムゾーンなし。Excel はパーツのタイムスタンプを正規化するので、ブックの本当の編集履歴はここではなく docProps/core.xml にあります。
122Last modified dateMS-DOS のパック形式の日付で、1980 年起点。ブック自身の日付システム(1900 年、オプションで 1904 年からの日数)と並べて覚えておく価値があります。無関係な 2 つの起点が同じファイルに同居しているわけです。
144CRC-32このパーツの非圧縮バイト列のチェックサム。Excel は読み込み時にこれを検証するので、転送中に壊れたブックは中途半端に開いて数字が狂うのではなく、きちんと失敗します。
184Compressed sizeこのパーツの deflate バイト数。FF FF FF FF なら ZIP64 の extra field に委ねますが、それが必要なほど大きいブックはたいてい別のところで既に間違えています。
224Uncompressed sizeパーツの元の長さ。この値と圧縮後サイズの差こそ、共有文字列の設計が効いている場所です。プールされたテーブルは格納サイズの何倍にも膨らみます。
262File name lengthOOXML の書き手はどれも [Content_Types].xml を先頭に置くので、そのときは 13 00(19 バイト)になります。ファイルの実際の種類について何かを語る最初のフィールドです。
282Extra field lengthExcel が書いたものなら通常はゼロ。スクリプトで再パックしたブックは Unix のパーミッションやタイムスタンプの extra field を拾いがちで、機能は何も変わりませんがファイルのハッシュは変わります。
3019First entry name[Content_Types].xml。その中の Override 要素が /xl/workbook.xml を spreadsheetml.sheet で終わるコンテンツタイプに対応づけていて、この文字列こそが「このパッケージは文書でもプレゼンでもなくブックである」という正式な宣言です。
variablevariablexl/workbook.xmlこのパッケージを表計算にしているパーツです。オフセットは固定ではないのでセントラルディレクトリ経由で探します。各シートとそのリレーションシップ id を列挙しており、id は xl/_rels/workbook.xml.rels 経由で実体の xl/worksheets/sheetN.xml に解決されます。
-224End of central directory signature50 4B 05 06。アーカイブコメントが無ければ末尾から 22 バイトの位置です。ブックのシートを列挙するのに必要なものはすべてここから辿ります。つまり最後の 22 バイトのほうが最初の 30 バイトより重要だということです。
-64Offset of the central directoryディレクトリの開始位置を、ファイル先頭からの絶対位置で示します。パッケージの前に何バイトか足されるとこの値は無効になり、Excel は本当のオフセットを探しに行かず、読めないファイルだと宣言します。

似た形式との見分け方

紛らわしい形式見分け方
Word 文書(docx)ローカルファイルヘッダの全フィールドが同一で、オフセット 30 も同一です。どちらのパッケージも [Content_Types].xml で始まるからです。分かれ目はファイル末尾のディレクトリ一覧で、ブックなら xl/workbook.xml と xl/ ツリー、文書なら word/document.xml と word/ ツリー。拡張子を読むのは代わりになりません。Excel はバイトが言うとおりのものを開きます。
xls前の世代であり、まったく別物です。D0 CF 11 E0 A1 B1 1A E1 で始まる Compound File Binary コンテナで、中に 'Workbook' という名前のストリームを持ちます。どちらも Excel で開き、どちらも「Excel のファイル」と呼ばれますが、行と列の上限がまるで違います。バイナリ形式は 65536 × 256、.xlsx は 1048576 × 16384。世界の大半が変換した実務上の理由がこれです。
csv現場では絶えず混同されますが、バイトレベルでは一度も似ていません。CSV は署名を一切持たないプレーンテキスト、.xlsx は ZIP です。痛い違いは意味のほうにあります。CSV が運ぶのは値だけ、ブックが運ぶのは値に加えて数式・型・書式・複数シート。だから「CSV でエクスポート」はファイルの大半を捨てる操作で、「CSV を Excel で開く」は元々なかった型を勝手にでっち上げる操作です。
xlsmマクロ有効のブックで、ヘッダを通して .xlsx とバイト単位で同一です。違いは xl/vbaProject.bin パーツがあることと、宣言されたコンテンツタイプが異なることだけ。目に見える違いが拡張子しかなく、リネームは無料なので、メールフィルタはパッケージを開かないとどちらか判定できません。

よくある壊れ方

  • end-of-central-directory レコードが失われている。ダウンロードが途中で切れても各ワークシートのパーツは無傷で正しく圧縮されたまま残りますが、それでも Excel は開こうとしません。列挙が末尾から始まるからです。50 4B 03 04 を前方に拾ってディレクトリを組み直せば、たいていすべてのシートが戻ります。
  • パッケージの前にバイトが付いた。50 4B 03 04 の前にプロキシのエラーページや余計な BOM が入るとファイル全体がずれ、セントラルディレクトリの絶対オフセットがその分だけ狂います。ブックは丸ごと存在しているので、前のゴミを削れば元に戻ります。
  • テキストモード転送。deflate ストリーム内の改行変換はヘッダもエントリ名もサイズも綺麗に残すので、パッケージは正しく一覧でき、シートを展開する段になって CRC で落ちます。事前に気づける手掛かりは ZIP の構造の中にありません。
  • 手で編集したパーツを誤って再パックした。シートがただの XML なので直接いじりたくなりますが、XML 宣言の前に BOM を入れる、エントリ名の大小文字を変える、フォルダのディレクトリエントリを含める。どれをやってもアーカイブツールは健全と言い、Excel は拒否します。
  • xl/sharedStrings.xml が壊れている。セルのテキストはプールされてインデックスで参照されるので、このパーツ 1 つの破損はセル 1 つを空にするのではなく、ブック中の文字列インデックスをまとめてずらします。結果、正しい数値に間違ったラベルが付いたシートが開きます。この形式が抱える障害の中で、最も人を誤らせるものです。

この形式の現在地

.xlsx は、多少なりとも構造のある表データを受け渡す事実上の共通形式です。その普及は技術というよりビジネス上の事実で、財務も業務も行政もこれで公開するから、あらゆるデータツールが読めるようにするしかありません。技術的にも、この用途としては悪くない形式です。公開された ISO 標準で、圧縮が効き、パーツが XML なので復旧しやすく、大量エクスポートを不可能にしていた .xls の行数制限もありません。一方でデータ処理用の形式としては貧弱です。パースには展開して数 MB の XML を流し込む必要があり、日付は 1900 年起点の連番で(しかも Lotus 由来のうるう年バグをわざと残したまま)、桁の多い数値 ID は黙って浮動小数点に丸められて指数表記に化けます。分析用途なら、単純な受け渡しは CSV、規模が要るなら Parquet のほうがよく、読み込み速度は桁違いです。.xlsx が本当に第一候補なのは、人が開いて編集する成果物のときです。数式も複数シートも書式もグラフも生き残りますが、CSV ではどれも残りません。

Excel ブック(xlsx)ファイルをこのサイトで開く

どれもブラウザ内で動きます。ファイルが端末から出ることはありません。

関連する形式

Excel ブック(xlsx)と混同しやすい形式です。先頭バイトを見比べてください。

形式先頭バイト拡張子
Word 文書(docx)50 4B 03 04.docx
PowerPoint プレゼン(pptx)50 4B 03 04.pptx
ZIP50 4B 03 04.zip
OLE2 / CFBD0 CF 11 E0 A1 B1.doc

よくある質問

ファイルのマジックナンバーとは何ですか?

ファイル先頭の数バイトで、名前が何であろうとその形式を示すものです。PNG は必ず 89 50 4E 47 で始まり、ZIP は 50 4B 03 04 で始まります。OS もブラウザも file コマンドも、拡張子を信用せずこのバイト列を読みます。だからファイル名を変えても中身の正体は変わりません。

マジックナンバーを自分で確認する方法は?

macOS や Linux なら xxd -l 16 ファイル名 で先頭 16 バイトが表示されます。Windows なら PowerShell で Format-Hex -Path ファイル名 -Count 16 です。あるいはこのサイトのファイル形式判別ツールにドロップすれば、ローカルでバイト列を読んで形式を教えてくれます。アップロードはありません。

2 つの形式が同じマジックナンバーを持つのはなぜ?

一方が他方の上に作られているからです。docx、xlsx、pptx、apk、jar、epub はすべて中身が ZIP アーカイブなので ZIP の署名で始まり、区別するには内部のエントリを見る必要があります。Java の class ファイルと macOS のユニバーサルバイナリはどちらも CA FE BA BE で始まり、直後のフィールドで見分けます。

マジックナンバーがまったくないファイルもある?

あります。XML、HTML、JSON、SVG、CSV といったテキストベースの形式には固定のバイト署名がないため、構造から判別します。先頭の <?xml 宣言、<svg 要素、あるいは { に続く引用符付きのキーなどです。これは確定ではなく推測なので、このリファレンスではそうした形式をプローブ判別として示しています。

マジックナンバーが一致すればそのファイルは安全?

いいえ。わかるのは形式であって、中身が無害かどうかではありません。正規の PDF や docx でも悪意のあるペイロードを含んでいることがあります。特に拡張子とバイト列が食い違うときに真の形式を知るのは有用な第一段階ですが、マルウェアスキャンではありません。

Excel ブック(xlsx)かもしれないファイルをお持ちですか?ファイル形式判別ツールで調べる — マジックナンバーをローカルで読み取ります。アップロードは一切ありません。またはすべての形式を見る。