😪

Wordさんは今もおつかれのままなのか?

2024/01/31に公開

背景と結論

ある日、同僚から言われました。

👨‍💼 「送ってもらったWordファイル、重すぎて開けないんだけど」

納期直前の追い込みからクレーム対応まで共に戦った仲間です。
「知らないよ、軽くしたいならMarkdownで勝手に書き直してよ」なんて決して思いません。

ただ何も返事をせずにWord 重いで検索していると興味深い記事がヒットしました。

Wordファイルを扱っていて「だんだん重くなっていく」と感じたことはないだろうか。特に、代々引き継がれてきたファイルほど、修正や保存が重くなる、と感じたことはないだろうか?あなたのその感覚は正しい。長い間修正され続け、重くなったWordファイルを、個人的に「疲れたファイル」と呼んでいる。

ぜひリンク先をご一読いただきたいですが、この記事で特に注目したいのは

という事実です。つまり同僚の文句は

🤔 Mac版のWordで修正しているから徐々に重くなっているのでは?

という可能性があります!

しかし、上述の記事は2018年の投稿、すなわち6年も昔の情報です。
本記事ではWordファイルの内部構造を眺めながら、実際にバグが修正されているかを確認してみました✍️

先に結論を言うと、不具合は修正されていました。
Wordさんはもうお疲れではありません!

調査

検証に使用した Word は今日 (2024/01/29) 時点で App Store で配信している最新版 (v16.81) です。

word_version

その他、実行環境については以下にまとめておきます。

実行環境とマシンの情報
$ system_profiler SPHardwareDataType | grep -E 'Model Name|Chip'
Model Name: MacBook Pro
Chip: Apple M1 Pro

$ sw_vers
ProductName:		macOS
ProductVersion:		13.5.1
BuildVersion:		22G90

プレーンテキストを保存してdocxファイルの中身を見る

それでは調査していきましょう。まずは適当な文章を記入したファイルを保存します。
余計な修正をすると差分を保存されてしまいそうなので、事前にコピーしておいたプレーンテキストをペーストして即座に保存しました。

Are you still tired?

保存された.docxファイルの実態は単なるzipファイルで、その内部にはxml形式のファイルが詰まっています。
中身を確認するため、そのまま解凍してみましょう。

$ unzip ./AreYouStillTired\?.docx
Archive:  ./AreYouStillTired?.docx
  inflating: [Content_Types].xml
  inflating: _rels/.rels
  inflating: word/_rels/document.xml.rels
  inflating: word/document.xml
  inflating: word/theme/theme1.xml
  inflating: word/settings.xml
  inflating: docProps/core.xml
  inflating: word/fontTable.xml
  inflating: word/webSettings.xml
  inflating: word/styles.xml
  inflating: docProps/app.xml

中身を見てみましょう。

$ tree . -a
.
├── AreYouStillTired?.docx
├── [Content_Types].xml
├── _rels
│   └── .rels
├── docProps
│   ├── app.xml
│   └── core.xml
└── word
    ├── _rels
    │   └── document.xml.rels
    ├── document.xml
    ├── fontTable.xml
    ├── settings.xml
    ├── styles.xml
    ├── theme
    │   └── theme1.xml
    └── webSettings.xml

6 directories, 13 files

先述の記事のディレクトリ構造と比較するとnumbering.xmlが見つからないことに気づきます😲
このファイルは箇条書きや段落番号の付与による情報を保持するファイルのようです。今回は単純なテキストのみなので妥当な結果だと言えそうですね。

さて、それでは問題の./word/document.xmlファイルから<w:body>要素を見てみます。
初期状態では読みにくいのでフォーマッタをかけて整理しています。

<w:body>
    <w:p w14:paraId="6EF66A82" w14:textId="3358E6FD" w:rsidR="00C15B1C" w:rsidRDefault="001677CA">
        <w:r w:rsidRPr="001677CA">
            <w:t>Are you still tired, Mr. Word?</w:t>
        </w:r>
    </w:p>
    <w:sectPr w:rsidR="00C15B1C">
        <w:pgSz w:w="11906" w:h="16838"/>
        <w:pgMar w:top="1985" w:right="1701" w:bottom="1701" w:left="1701" w:header="851" w:footer="992" w:gutter="0"/>
        <w:cols w:space="425"/>
        <w:docGrid w:type="lines" w:linePitch="360"/>
    </w:sectPr>
</w:body>

ちょっとよくわからないですね。ChatGPT4にテーブル形式でまとめてもらいました。
ちょっと怪しい記載もあるので取り扱いにはご注意ください。

要素 属性 説明
w:p w14:paraId 段落の一意な識別子
w14:textId テキストの一意な識別子
w:rsidR この段落が作成または変更されたリビジョンの識別子
w:rsidRDefault この段落のデフォルトのリビジョン識別子
w:r w:rsidRPr この実行範囲のプロパティが最後に修正されたときのリビジョン識別子
w:t 実際のテキストを含む要素
w:sectPr w:rsidR このセクションのプロパティが最後に修正されたときのリビジョン識別子
w:pgSz w:w, w:h ページの幅と高さを指定
w:pgMar w:top, w:right, w:bottom, w:left, w:header, w:footer, w:gutter ページの各種余白を指定
w:cols w:space ページのカラム間のスペースを指定
w:docGrid w:type, w:linePitch グリッドの設定を指定、特に行送りの高さなど

なるほど、これらの情報は概ね以下の3つに分類して整理できそうです。

  • 段落等の情報の識別子: paraId, textId
  • リビジョンの識別子: rsidR, rsidRPr など
  • ページの幅や余白などの情報: w:top, w:space など

ここで注目したいのはrsidです。これはrevision idの略称なので、Gitのリビジョンと同じ意味合いです。
Wordでは校閲機能などで差分が確認できますが、xmlの構造としてはこのタグで管理されているようです。

ここまで見て、過去の記事と比べてかなりxmlの形式が異なっていることに気づきました。
採用しているOpenXMLのバージョンに更新が入ったのでしょうか…?

少しだけ改変するとどのように変化するか

以上の情報を踏まえた上で、適当な文字!を挟んでから保存してみます。

You are still tired!

改めて./word/document.xmlを見てみます。すると差分がたくさん出ていました🤯

 <w:body>
-    <w:p w14:paraId="6EF66A82" w14:textId="3358E6FD" w:rsidR="00C15B1C" w:rsidRDefault="001677CA">
+    <w:p w14:paraId="6EF66A82" w14:textId="3B518981" w:rsidR="00C15B1C" w:rsidRDefault="001677CA">
        <w:r w:rsidRPr="001677CA">
-            <w:t>Are you still tired, Mr. Word?</w:t>
+            <w:t xml:space="preserve">Are you still </w:t>
+        </w:r>
+        <w:proofErr w:type="gramStart"/>
+        <w:r w:rsidRPr="001677CA">
+            <w:t>tired</w:t>
+        </w:r>
+        <w:r w:rsidR="00010F2E">
+            <w:t>!</w:t>
+        </w:r>
+        <w:r w:rsidRPr="001677CA">
+            <w:t>,</w:t>
+        </w:r>
+        <w:proofErr w:type="gramEnd"/>
+        <w:r w:rsidRPr="001677CA">
+            <w:t xml:space="preserve"> Mr. Word?</w:t>
        </w:r>
    </w:p>
    <w:sectPr w:rsidR="00C15B1C">
        <w:pgSz w:w="11906" w:h="16838"/>
        <w:pgMar w:top="1985" w:right="1701" w:bottom="1701" w:left="1701" w:header="851" w:footer="992" w:gutter="0"/>
        <w:cols w:space="425"/>
        <w:docGrid w:type="lines" w:linePitch="360"/>
    </w:sectPr>
 </w:body>

ここから分かる変化は、

  1. textIdが更新されている
  2. <w:proofErr w:type="gramStart"/>属性が追加されている
  3. w:rsidRPr=001677CAが複数に分割され、その内部にw:rsidR="00010F2Eが割り込んでいる

1.のtextIdは、その要素内に更新が入ると新規に発行される仕様ということでしょう。
次に、スクリーンショット中の下線部からわかるように、2.は文法チェックの警告情報が付与されたためです。これらもxml内で管理されるわけですね。
3.は更新履歴に該当しており、w:rsidR="00010F2E<w:proofErr w:type="gramStart"/>が割り込んだことにより分割されている、と言えそうです。

2行が削除され16行が追加されているわけですから、これを繰り返せば次第にパースが大変になっていくのは明白ですね😲

もとに戻すとどうなるか?

しかし、これらはWordの挙動を実現するために必要な情報です。大切なのは

  • 差分情報がない状態、すなわち元のリビジョンに戻したときに
  • それまでの変更履歴がちゃんと削除されて断片化しない

ということです。次にこれを確認しましょう。

もう一度Wordを開き、!を削除してから保存します。

Are you still tired?

この状態で./word/document.xmlをはじめの状態と比較してみます。

 <w:body>
-    <w:p w14:paraId="6EF66A82" w14:textId="3358E6FD" w:rsidR="00C15B1C" w:rsidRDefault="001677CA">
+    <w:p w14:paraId="6EF66A82" w14:textId="41840607" w:rsidR="00C15B1C" w:rsidRDefault="001677CA">
        <w:r w:rsidRPr="001677CA">
            <w:t>Are you still tired, Mr. Word?</w:t>
        </w:r>
    </w:p>
    <w:sectPr w:rsidR="00C15B1C">
        <w:pgSz w:w="11906" w:h="16838"/>
        <w:pgMar w:top="1985" w:right="1701" w:bottom="1701" w:left="1701" w:header="851" w:footer="992" w:gutter="0"/>
        <w:cols w:space="425"/>
        <w:docGrid w:type="lines" w:linePitch="360"/>
    </w:sectPr>
 </w:body>

うまく戻りましたね!
要素内の情報が書き換えられたので、同様にtextIdが更新されています。
その一方、!が割り込んでいたテキスト部分は元通りに結合され、一つのrsidRPrとして保存されました。
すなわち余計な要素の断片化は起こっておらず、Wordさんはお疲れにならずに済んでいるようです!

まとめと参考にさせていただいた記事

Mac版のWordでのみ発生していたバグは修正され、Wordさんは元気にやっているようでした😌
調査するまでは「なるべくWordはWindows版で修正した方がいいのかな?」と感じていましたが、この結果ならひとまず安心して使えそうです。

Wordはそれほど頻繁に使うわけではありませんが、たまには身近なツールの中身を覗いてみるのも楽しいですね。
Excelも内部的な処理はちょっと気になるので、気が向けば調べて見るかもしれません。

本記事の調査には以下のページも参考にさせていただきました。
OpenXMLも奥が深そうですね…。

あ、冒頭のWordファイルが重かったのは画像の貼り付けすぎが原因です🫠

Discussion