Microsoft Officeのファイルフォーマットはなぜこんなに複雑なのか?

圧縮キャリアが出来るまで
Sponsored Link

Microsoft Officeのファイルフォーマットはなぜこんなに複雑なのか?

Microsoft Officeファイルフォーマットはなぜこんなに複雑なのか?(対処法つき)

2008年2月19日(火) ジョエル・スポルスキ

先週、マイクロソフトはOfficeバイナリファイルフォーマットを公開した。このフォーマットは、まったく気狂いじみて見える。たとえばExcel 97-2003 のファイルフォーマットは、349ページものPDF文書だ。でもちょっと待った、まだこれで全部じゃないんだ。この文書には、以下のようなコメントが書いてある:

すべてのExcelワークブックはcompound fileに格納される。

つまり、Excel 97-2003のファイルはOLE compound documentで、それは要するに、一個のファイルの中に構築されたファイルシステムのようなものなのだ。その仕組みはもちろん複雑で、それを理解しようとしたらまた別の9ページの仕様書を読まなくちゃならない。そしてその「仕様書」は、伝統的ないわゆる仕様書というよりも、むしろCの構造体定義みたいに見える。丸ごと一式の階層的ファイルシステムっていうのはそういうものだ。

自作のblogシステムにWord文書をインポートするための便利なプログラムを作ってみようとか、家計簿データからExcelフォーマットのシートを作ってみようとか、そんな日曜大工的な目的でこのドキュメントを読み始めた人がもしいたとしても、あまりに複雑で巨大な仕様のおかげで、そんな考えは幸いにして一瞬で消し飛んでしまうことだろう。普通のプログラマがOfficeバイナリファイルのフォーマットについていだきそうな感想は、こんなものだと思う:

* Officeファイルのフォーマットは、意図的に分かりづらく撹乱されている。
* Officeファイルのフォーマットは、発狂したボーグによって生み出された。
* Officeファイルのフォーマットは、途方もなく無能なプログラマによって作成された。
* そして、こんなものを正しく読み書きすることは不可能である。

でもこの四つの考えはすべて誤っている。ここで私は、少しだけ背景を掘り下げながら、なぜOfficeのファイルフォーマットがこれほど信じ難いまでに複雑なのかを説明してみたい。そうすれば、Microsoftのプログラミングがまずいせいでこうなっているわけではないということが分かるだろう。そして、この複雑なOfficeファイルフォーマットを扱うための方法も示したいと思う。

Officeファイルフォーマットは、非常に古いコンピュータでも高速に動作するために設計された。
Windows版Excelの初期バージョンは、1MBのRAMと80386 20MHzで快適に動作しなければならなかったのだ。このためファイルフォーマットにおいても、ファイルを極力高速に開き保存することができるようにするために、 多くの最適化がほどこされている:

* Officeファイルはバイナリフォーマットである。つまり、ディスクからメモリに一連のバイトをコピーするだけで、利用可能なCの構造体ができ上がるようになっていて、ファイルの読み込み時に字句解析構文解析も不要になっている。もちろん字句解析や構文解析は、ビット列のコピーよりも何オーダー分も遅い。
* よく行われる操作を高速化するために必要とあらば、ためらいもなくファイルフォーマットがゆがめられている。たとえばExcel95と97には「Simple Save」という機能があり、これはOLE compound documentのフォーマット(これは普通の用途にとっては遅すぎた)よりも高速に保存をするための手段として使うことができた。またWordには「Fast Save」という機能があった。これは、大きな文書を高速に保存する際に文書全体を保存し直すのではなく、変更点だけを末尾に追加する、という方式で、当時の記憶装置の性能からすると、大きな文書を保存するのにかかる時間を30秒から1秒にする効果があった。(でもそのせいで、削除されたデータがファイルに残り続けることになり、望ましくない結果にもなったのだが。)


Officeファイルフォーマットは、ライブラリの利用を前提として設計された。
Officeバイナリファイルをインポートするプログラムスクラッチから書こうと思ったら、描図のためのWindows Metafile Formatとか、OLE Compound Storageとか、そういう代物をサポートしなければならない。いわゆるWindows環境で作業をしているならば、ライブラリがあるのでそういうものをサポートするのは簡単だ。つまりこういう仕組みを利用するのは、Microsoftの開発チームにとっては便利なショートカットだったわけだ。でもすべてを一から開発しようとする人は、こういうものすべてを自力で作り上げなければならない。
OfficeはOLE compound documentを全面的にサポートしているので、例えば、Word文書の中にスプレッドシートを埋め込むとか、そういうことができる。Word文書のファイルを完璧に扱えるようになるためには、その中に埋め込まれたスプレッドシートも何とかうまく扱えるのでなければならないだろう。

Officeファイルフォーマットは、相互運用性(interoperability)を念頭に置いて設計されたわけではない。
例えばWordファイルフォーマットは、Wordからさえ読み書きできればそれで良い、というのが開発当時の前提で、それは当時としては決して間違った考えではなかった。だから、Word開発チームのプログラマがファイルフォーマットの仕様をどう変えようかと検討する際に気にかけたのは、(a)どうすれば動作が速いか、(b)既存のWordのコードベースを元にして、もっとも少ない行数の変更で済ませるにはどうすれば良いか、ということだけだったのだ。 SGMLとかHTMLのような、交換可能な標準化されたファイルフォーマット、というアイディアがようやく受け入れられたのは、インターネットのおかげでドキュメントの大規模な交換が現実的になってからで、そしてそれは、Officeバイナリファイルのフォーマットが最初に決められてから十年も後の話だ。
また文書の交換方法ということについて言えば、ドキュメントをやり取りしたいならばインポート/エクスポート用の変換を介せば良い、という前提も常にあった。Wordにはほぼ最初期以来、交換を容易にするために設計されたRTFというフォーマットがあり、それは今でも100%サポートされている。

Officeファイルフォーマットは、アプリケーションのあらゆる複雑性を反映せざるを得ない。
Microsoft Officeについているすべてのチェックボックスや書式設定オプションの仕様が、ファイルフォーマットのどこかには表現されているのでなければならない。たとえば、Wordの段落メニューには「次の段落と切らない」というチェックボックスがあって、それは指定された二段落間に改ページが入らないように、必要があればその段落を次のページに移動するんだけど、そのチェックボックスの情報も、もちろんファイルフォーマットに含まれているのだ。だから、もしWord文書を正しく表示できる完璧クローン品を作ろうと思うならば、その仕様もちゃんと実装しなければならない。たとえばあなたがWord文書を読み込むことができる競合ワープロ製品を開発しているとして、ファイルフォーマットからそのオプションを表す1ビットロードするプログラムを書くのには、1分しかかからないだろう。でも、あなたの製品のページレイアウトアルゴリズム修正してそのオプションが効くようにするには、きっと何週間もかかることだろう。もしそのオプションが効くようにしなければ、その製品のユーザーが自分のWord文書をそれで開いてみた時に、全ページがぐちゃぐちゃになっているのを見ることになる。

Officeファイルフォーマットは、アプリケーションの歴史を反映せざるを得ない。
ファイルフォーマットの複雑さの少なからぬ部分は、古く、ややこしく、一般に好まれておらず、ほとんど利用もされないような仕様のせいで生じている。そういう部分は、下位互換性を維持するために相変わらずファイルフォーマットの中に残っているのだ。何にせよ、既に存在するコードをそのまま存在させて置くこと自体のコストは、Microsoftにとってゼロなわけだから。でももしあなたが本気でOfficeファイルフォーマットの読み書きを完璧にやってのけようとするならば、きっと十五年前にどこかのインターンがMicrosoftでやった仕事の一つ一つまでを、そっくりあなたがやる必要があるだろう。否定できない事実は、現行のWordおよび Excelができるまでには、何千人年の開発工数が投入されているということだ。そうである以上、本気でWordとExcelのクローンを作ろうとするならば、何千年も働かなければならないだろう。ファイルフォーマットは、アプリケーションがサポートしている全仕様の簡潔な要約のようなものに過ぎないのだ。

雰囲気をつかむために、あるちょっとした例について掘り下げて考えてみよう。Excelワークシートというのは、いろんな種類のBIFFレコードの集まりなのだが、ここでは仕様書で最初に書かれているBIFFレコードを調べてみたい。その名前は「1904」という。
Excelファイルフォーマット仕様書の記述は、このレコードの意味についてはひどく不明瞭だ。そこに書いてあるのは、1904レコードは「1904日付システムが利用されているか否か」を表すということだけだ。うんそうだね、古典的な使えない仕様書ってやつだ。もしあなたがExcelファイルフォーマットを扱わなくちゃならない開発者で、この仕様書を読んだとしたら、きっとMicrosoftは何かを隠しているに違いないと思うだろう。確かにこの記述だけでは全然不足で、この問題を理解するためにはいくつかの周辺知識が必要になる。それをここで教えてあげよう。
Excelワークシートには二種類あって、それは基準日付が1900/1/1になっている(そして、Lotus 1-2-3との互換性のため、閏年バグが意図的に埋められている)ものと、基準日付が1904/1/1になっているものとだ。Excelが両方の方式をサポートしている理由は、Mac版 Excelの最初のバージョンは、OSの基準日付をそのまま利用した(容易だったから)のに対して、Windows版Excelは、1-2-3のファイルをインポートするために1900/1/1を基準日にしたからだ。どう、もう泣きが入った? 歴史上のどの時点においても、プログラマは正しくないことをしたわけではない。でも、結果として出来上がったのはこれだ。


1900年方式のファイルも1904年方式のファイルも、どちらも世の中にはいっぱい転がっていて、それはそのファイルの誕生が WindowsであったかMacであったかによるのが普通だ。一方の方式を他方の方式に勝手に変換してしまうと、何らかの整合性エラーが発生する恐れがあ るので、Excelは勝手に方式を変更してはくれない。つまりExcelファイルを読み込むためには、両方の方式を扱えなければならないのだ。これは単純 にファイルから1ビットを読み込めば済むという話ではなく、日付表示と日付解析のコードを、両方の基準日に対応させるために書き直さなければならない、と いうことなのだ。その実装には数日はかかるんじゃないだろうか。
さらに言えば、Excelクローンを作ろうとする過程では、Excelでの日付の扱いに関するありとあらゆる微妙な問題に気づくことになるだろ う。Excelは、いつのタイミングで数値を日付に変換するのか? 日付フォーマッティングはどのように動作するのか? なぜ「1/31」は今年の1月 31日になるのに、「1/50」は1950年の1月1日になるのか? こういった微妙な仕様の数々は、結局Excelのソースコードと同じ分量の仕様書を書くのでない限り、完璧に文書化することなどできやしない。
そしてこれは、Excelクローンを作るとしたら扱わなければならない何百ものBIFFレコードの中の最初の一つに過ぎず、しかも最も簡単なものの一つなのだ。多くのBIFFレコードは、熟練したプログラマであっても泣きが入るに違いないほど複雑怪奇である。

結局のところ、結論は一つだ。Microsoftがファイルフォーマットを公表したことは、MicrosoftおよびOfficeにとっ ては大変役に立つことだった。だがそれによって、Officeファイルの読み込みや保存をおこなうことが、他人にとっていくらかでも容易になったわけでは ない。Officeは死ぬほど複雑で豊穣なアプリケーションであって、そして、最もよく使われる20%の機能を実装することによって80%のユーザーを満足させることができる、という考えは誤っているのだ。バイナリファイルの仕様書はせいぜい、リバースエンジニアリングにかかる数分の手間を省いてくれるだけのものに過ぎない。

さて、対処法を教えるって約束していたんだったね。まず良い知らせは、ほとんどすべての普通のアプリケーションにとって、自力でOfficeバイナリファ イルを読み書きしようとするのは間違った考えだということだ。真剣に考慮すべき有力な代替案が二つある:それは、Officeに仕事をやらせるか、あるい は、もっと書き易いファイルフォーマットを利用するか、ということだ。

大変な仕事はOfficeにやらせろ。
WordとExcelは、COM Automation経由で利用可能な、恐ろしく完成度の高いオブジェクトモデルを内包していて、そのおかげで、プログラムによってどんな操作でもするこ とができる。多くの状況では、Office内部のコードを再利用する方が、それを再実装しようとするよりも幸せになれるはずだ。例えば:
  1. 既存のWordファイルをPDFフォーマットに出力するWebアプリケーションを作っているとしよう。私ならこうする:数行のWord VBAコードでファイルを読み込んだ後、Word 2007に組み込まれているPDFエクスポーターを使ってそれをPDFファイルとして保存する。このコードは、IIS上で動いているASPや ASP.NETから直接呼び出すことができる。これだけで動くのだ。最初にWordを起動する際には数秒かかるだろうが、二度目以降には、COMによって Wordはメモリ上に保持されているはずだから、普通のWebアプリケーションとしては十分な性能が出るはずだ。
  2. 上と同じだが、環境がLinuxだとしよう。Windows 2003 Serverを買って、ちゃんとしたライセンスのあるWordをそれにインストールして、上のようなことをする小さなWebサービスを作りたまえ。C#とASP.NETを利用すれば半日の仕事だ。
  3. 上と同じだが、スケーラビリティが要求されるとしよう。上の2のような箱をいくつでも作って、その前にロードバランサを置いておきたまえ。コード書きは不要だ。
この種のアプローチは、Office系のアプリケーションをサーバ上で動かしたいあらゆる場合に役に立つはずだ。例えば:
  • Excelワークブックを開き、セルに値を入力し、計算し、セルから値を取得したい。
  • GIFフォーマットのチャートをExcelに生成させたい。
  • ファイルフォーマットに関する考慮なんか一分もすることなしに、Excelワークシートから何らかの情報を引き出したい。
  • ExcelファイルをCSVデータに変換したい。(別のやり方としては、Excel ODBCドライバを使ってSQLで引くという手もあるね。)
  • Word文書を編集したい。
  • Wordの定型フォームを埋めたい。
  • Officeによってサポートされている、いろんなファイルフォーマット間の変換をおこないたい。(Officeには、何十種類ものワープロやスプレッドシートファイルのインポート機能がついている。)
もちろん、動作モードが対話的ではないということをOfficeオブジェクトに教える方法はいくらでもあるから、上のすべてのケースで、画面の描画とか入 力プロンプトとかで煩わされる心配はない。ところで、このやり方にはちょっとした有効な工夫がいくつかあり、それはMicrosoftによって公式にはサ ポートされていない。だから、まずknoledge baseを読んだ方が良いよ。

ファイルを書くには、もっとシンプルなフォーマットを使え。
もし、単にOfficeドキュメントをプログラムで新たに作成することが必要なのだとしたら、ほとんどすべての場合に、Officeバイナリフォーマットよりも適切で、しかもWordやExcelでまったく問題なく開くことのできるフォーマットがある。
  • Excelのための表データが必要ならば、CSVを考慮せよ。
  • CSVでは足りない計算機能がどうしても必要ならば、WK1フォーマット(Lotus 1-2-3)はExcelとは比較にならないほどシンプルで、しかもExcelでちゃんと開くことができる。
  • 本当に、どうしても、Excelネイティブのファイルを作成しなくちゃいけないならば、ものすごく古いバージョンのExcel(compound document関連の何やかやが導入される以前のExcel 3.0は良い選択だ)を持って来て、自分が使いたい最低限の仕様のみを使ったファイルをセーブしたまえ。そしてそのファイルを調べて、最低限出力しなけれ ばならないBIFFレコードが何であるかを把握し、その上でその部分の仕様書を読むといい。
  • Word文書については、HTMLを考慮せよ。Wordでちゃんと開ける。
  • どうしても凝ったWord文書を作成したいのならば、たぶん一番良い方法はRTF文書を作ることだ。WordができることはすべてRTFで表現で きるにもかかわらず、RTFはテキストフォーマットなので、それを簡単に書き換えることができる。まず、埋め草を入れた凝ったフォーマットの文書を Wordで作成し、それをRTFで保存する。そして、テキスト置換で埋め草を変換すれば、どのバージョンのWordでも開けるRTF文書の出来上がりだ。
いずれにせよ、文字通り全Office文書を完璧に読み書きできるOfficeの競合製品を作り上げようというのでない限り(そのためには何千年分の仕事 が必要)、あなたが抱えている問題が何であるにせよ、Officeバイナリフォーマットを読み書きしようとするのは、間違いなくいちばんの苦労が約束された道だ。
Sponsored Link

カテゴリ

コンテンツ

名前:大垣伸悟
学歴:立命館大学→慶応義塾大学→東亜大学大学院
お気に入りサイト:http://jayg-million.jugem.jp/
参考サイト:果たしてそこに正義はあるか
twitterJ_A_Y_G
own.jpg 16歳で単身渡米した後、アメリカプロ野球選手野球 http://azneyland.55street.net/baseball/history/2003.htm ⇒エージェント(野球選手時代の後半に並行して) ⇒教師(情報システム系) ⇒ソフトウェア製品企画開発(日本シェアbPの大企業向けERPパッケージ製品) ⇒人事 ⇒採用広報(ついに海外にまで採用活動進出。日本最大級のインターンシップを開催する採用といえば・・・)  http://job.yomiuri.co.jp/news/special/ne_sp_08072201.cfm  採用として私が企画運営した横浜FCとのスポーツビジネスもののインターンシップが記事になっていました ⇒そして現職へ 世界の底辺から這い上がり、苦痛の時期を経験し、今やっとこうして何とか生きています。 北米10都市を回って、NYマンハッタン、LA、などでも活動。 ※大学・大学院も全て飛び級