Google ドキュメントを一度通すと Word が壊れる — その docx を OOXML まで降りて直した話
Google ドキュメントを一度通した Word 文書(.docx)が、開いた瞬間に「フォントが見つかりません。代替フォントを使用しました」と黄色いバーを出す。段組みが崩れ、漢字の字形も中国寄りに歪む。送り主のせいではなく、ファイルそのものが壊れていた——その正体を OOXML まで降りて突き止めた。
何が起きていたか
問題のファイルを健全なものと並べると、症状はだいたい 4 つに集約された。
- 段組みの間隔が他のファイルと違う
- 一部の漢字が、よく見ると微妙に違う字形で表示されている(経・総などが、わずかに中国寄りの形)
- 編集中にコピー&ペーストで Word が不安定になる
- 日本語の文章なのに、校正が英文ルールで動いて妙な指摘を出す
共通点を探していくと、症状の出るファイルは全部「いったん Google ドキュメントで編集された .docx」だった。誰かが Google ドライブ上で開いて直し、また .docx として書き出してメールに添付し直した——その経路を通ったものだけが壊れていた。
.docx の中を開けてみる
.docx は、実体は zip で固められた XML の束だ。拡張子を .zip に変えて展開すれば中身が見える。主要なのはこのあたり。
- word/document.xml — 本文
- word/styles.xml — スタイル定義(標準・見出しなど)
- word/settings.xml — 文書全体の挙動設定
健全版と汚染版で、この 3 つを並べた。すると、英文ワープロのクセが至るところに混入しているのが見えてきた。
- styles.xml のフォント指定 — 健全な日本語文書: 明朝・ゴシックのみ / Google を通した文書: Georgia が紛れ込む
- 文字単位の言語設定 — 健全な日本語文書: 指定なし(=日本語既定) / Google を通した文書: en-US や zh-TW(繁体字)が混入
- 段組みの間隔 — 健全な日本語文書: 425 / Google を通した文書: 720
- 日本語互換オプション 6 種 — 健全な日本語文書: 全部そろっている / Google を通した文書: 全部消えている
- 既定のタブ幅 — 健全な日本語文書: 840(約 14.8mm) / Google を通した文書: 720(約 12.7mm)
- 句読点の詰め設定 — 健全な日本語文書: 詰める / Google を通した文書: 詰めない
特に効いていたのが、settings.xml の中にある日本語互換オプション 6 種類の一斉消失だった。これは Word が日本語の文書を正しく組むための前提スイッチで、下線の引き方、全角と半角のバランス、改行後のふるまい、表組みの行の高さの補正などを束ねている。日本語版 Word なら必ず入っているはずのこれが、Google ドキュメントを通すと根こそぎ落ちる。だから「開いた瞬間に段組みが崩れ、行送りがおかしくなる」。
漢字が中国寄りの字形になるのも理屈は同じで、文字に zh-TW(繁体字)や zh-CN(簡体字)の言語タグが付いてしまっている。Word は言語タグを見て「この字は東アジアのどの言語用フォントで描くか」を決めるので、繁体字タグが付いた箇所だけ中国語フォントを当てに行く。フォントを明示していても、字形は中国側に寄る。
要するに、Google ドキュメントの書き出しは「英語圏のワープロの初期値」を docx に書き戻している。日本語 Word の作法を知らないまま上書きしていく。だから、一度通すだけで日本語文書としての前提がまるごと入れ替わってしまう。
直す——ただし本文には絶対に触らない
原因がわかれば直し方は決まる。本文の文字には一切触らず、設定とスタイルの「属性」だけを健全な値に戻せばいい。Python で zip の中の XML を直接書き換える小さなツールを書いた。
設計でいちばん神経を使ったのは、本文を絶対に壊さないことだ。修正の前後で本文テキストをすべて連結してハッシュ(SHA256)を取り、完全に一致することをプログラム自身に確認させた。ハッシュがずれたら処理を止める。この一本のガードを入れただけで、何度でも安心して修正をかけ直せるようになった。レビューも「ハッシュが一致しているか」を見るだけで済む。
途中、設計でいくつか落とし穴も踏んだ。たとえば「スタイル定義ごと健全版で上書きすればいい」と最初は考えたのだが、これは罠だった。文書ごとに固有のスタイルが本文から参照されているので、丸ごと差し替えると参照が切れて、Word がかえって全体を作り直して崩す。正解は「スタイルの骨格は残し、中に紛れた Georgia だけを抜く」という、外科手術のような最小修正だった。壊れているものを直すときほど、触る範囲を狭く保つことが効いてくる。
自分の本職に引きつけて考える
日々まわってくる文書のかなりの割合が、Word・Excel・Google ドキュメント・PDF のあいだを何度も往復しながら、複数の部署の手を渡っていく。今回の「Google を一度通すと壊れる」は、その往復のどこか一回に紛れ込んだ事故だった。そして、こういう事故は一度きりでは終わらない。来年も、別の様式で、同じ顔をして戻ってくる。
だからこそ、原因を「なんか壊れてた」で済ませずに OOXML のレベルまで言語化して、直すツールごとチームに残しておく価値がある。次に同じ症状が来たとき、ゼロから悩むのか、10 分で原因を当てて直すのかは、この一度きりの調査を言葉にして残したかどうかで決まる。文書整備という仕事は地味だが、地味な事故ほど再発するし、再発するものほど仕組みにする価値がある。
OOXML を生で読むのは最初は怖い。でも「本文のハッシュだけは絶対に守る」という一線さえ引いておけば、設定の手術は思ったより安全にできる。壊れた文書を前にしたとき、「送り主が悪い」でも「Word が悪い」でもなく、どの XML のどの属性がどう書き換わったのかまで降りていけると、原因も直し方も、そして「どこまで直すべきか」も、自分の手の内に戻ってくる。
関連書籍 (Amazon)
- データ指向アプリケーションデザイン(Martin Kleppmann/オライリー)— データの整合性と冪等性をどう設計で担保するか、を体系立てて論じた本。今回の「本文ハッシュで不変条件を守る」という発想の、もっと一般的な土台になる。
- リーダブルコード(Dustin Boswell, Trevor Foucher/オライリー)— 「触る必要があるものだけ触る」という外科的な修正の感覚を、コードの読みやすさの観点から鍛えてくれる定番。壊れたものを直すときほど効いてくる。
- Effective Python 第2版(Brett Slatkin/オライリー)— 今回のような「壊れやすいデータを、壊さずに安全に加工する」処理を Python で書くときの実践的な型が詰まっている。
時間を、ゆっくりに。 ─── longdrift