Excelファイル操作をプログラミングする前に、まずはxlsxをzipに変えて内部構造を見てみよう

こんにちは。ギークフィードの高橋敦史です。

業務システムあるあるにエクセルで出力してという要望があります。
不思議とWordの要望は少なくパワポに至っては聞かれたこともありませんが、Excelの入出力機能はなかなか需要がなくならないようです。

そこで我々エンジニアがExcel形式に対応したライブラリを使って開発することになりますが、作り込むうちに思わぬところで壁に当たったり、ほんのレイアウト調整程度で工数が溶けることもしばしば。
そんなエクセルさんと仲良くなるため、xlsx形式内部のデータ構造と調べ方を紹介しようと思います。

※xls形式や各種ライブラリの使い方には触れません。

 

Excel形式のファイル構造を一言で

十数年前までエクセルといえば「.xls」を拡張子に持ち、バイナリ形式で保存されるファイルでした。
それがExcel2007の登場と共に「.xlsx」拡張子が広まり、XML形式+zip圧縮が標準となっています。
つまり、現在の標準であるxlsx形式のファイルはzip解凍でき、中身は基本的にXMLということになります。

※仕様は「Office Open XML」として国際標準化されています。

 

xlsxファイルの中身を展開する

まず適当なXLSX形式のファイルを用意します。
新しいファイルを作成し、2シート設けて下図のような編集を加えておきます。
手入力したり、セルをコピペしたり、セル参照も設定、セルの入力書式を少々変更、あとは画像も挿入しておきましょうか。意味不明な場所ですが気にせず。。

 

保存して閉じたら、次に拡張子を「.zip」に変更します。
Windows環境で拡張子を表示しない設定にしている場合は、一時的に設定を変えて拡張子を表示してください。
拡張子変更の際、「ファイルが使えなくなる可能性」とOSから警告されても無視します。
拡張子が変わったら、あとは普通のzipファイルとして解凍すると、以下のようなファイル群が展開されます。

 

 

紙面の都合上、主要なものだけピックアップして紹介します。

 

_rels (階層内の)各パーツの関連性を定義
xl/media 挿入した画像ファイルの実体を格納
xl/sharedStrings.xml 全シートの全セルに入力された文字列を集約
xl/worksheets/sheetN.xml 各シートのデータを収納

 

つまりsheetN.xmlがシートの本体データで、装飾やテキスト・画像コンテンツはそれぞれ別の場所に保存されており、その参照関係がrelsファイルで定義されているという構造になっています。

 

XMLファイルを覗き見る

では具体的にXMLを覗いてみましょう。
そのままでは見づらいので、XMLエディタで整形します。

sharedStrings.xml

ここには全シートのテキストが集約されています。
しかしよく見ると、「次長」は2つのセルに入力されていますが、sharedStrings.xml内には一つしかありません。
また、年齢の「54」と「50」も見当たりません。一方で「46」だけは存在しますが、これはセルの書式を文字列にして入力したためです。

「役職」に対する読み方が「ヤクショクショク」となってますが、これは入力中に失敗して編集したものが残ってしまったようです。別セルにもう一度ミスなく「役職」と入力した場合は、異なるデータとして保存されます。

 

sheet1.xml

データは行ごとにまとめられていますね。
セルのデータは 0 のように数値になっていますが、これはsharedStrings.xmlの0番目の要素を指し示しています。
実は「次長」のセルはコピペしていたのですが、XMLを見ると同じ参照先(=6)になっています。
最後の方に <drawing r:id="rId2"/> というのがありますが、これが挿入した画像の定義情報です。

 

sheet2.xml

A列は参照設定をしていたので、データも参照先が入っています。
先程見当たらなかった年齢の「54」と「40」は 54 のように直接保存されていました。

 

sheet1.xml.rels

Id=”rId2″ のTargetとしてdrawing1.xmlが定義されています。先程sheet1.xmlで読み込まれていたものは、このリレーションシップを介して実体と繋がります。

 

 

さて、一通り主要なXMLにざっと目を通しました。
これでライブラリを使って実装する際も、関数の裏側でどのような操作が行われているか少しイメージが湧くのではないでしょうか。
 

データ量の多いExcelファイルの場合などロードするまでに時間がかかりますが、sharedStrings.xmlの仕組みが分かっていれば、なぜアクティブシートだけロードするのが難しいか理由が納得できると思います。

 

気持ちの悪い仕様

余談ですが、workbook.xml の中にこんな箇所があります。

添付資料でファイルを送ることなど普通にありますが、こんなところにローカルのパスが埋め込まれてたりするんですね。思わぬところでユーザ名やフォルダ分類がダダ漏れです。。

 

Excelのデータ構造を調べてみて

今回ご紹介したのは、ごくシンプルなxlsxファイルの一握りの情報でした。手順は簡単なので一度手元のPCで遊んでみてください。(もちろん壊れてもよいファイルで!)

変更後に差分を見たり、XMLを直接編集したものをzip化してxlsxに戻してみたり、操作に慣れておくと急な対応時に焦らずに済みます。

 

なお、Wordも同様のやり方でXMLに解体することができます。
試しに解体してみるとわかりますが、Wordの場合は何というかデザイン要素が半端なく入れ子状態になっていて、余計な要素を除去するところから始まる苦行の道になっています。
文字を打ち込んで、デザイン変えて、文字を削除すると空のデザインだけが残っているという。。

 

Excelがデータ中心なのに対し、Wordは装飾中心なのかなと個人的に思います。
ということでWord編の予定はありませんw

この記事が気に入ったら
いいね ! しよう

Twitter で
The following two tabs change content below.
サイト管理者
サイト管理者
株式会社ギークフィードのサイト編集担当者です。 弊社へのお問い合わせ・質問は、お問い合わせページからお願いいたします。

【採用情報】一緒に働く仲間を募集しています

採用情報
ページトップへ