Wordさんは今もおつかれのままなのか?
背景と結論
ある日、同僚から言われました。
👨💼 「送ってもらったWordファイル、重すぎて開けないんだけど」
納期直前の追い込みからクレーム対応まで共に戦った仲間です。
「知らないよ、軽くしたいならMarkdownで勝手に書き直してよ」なんて決して思いません。
ただ何も返事をせずにWord 重い
で検索していると興味深い記事がヒットしました。
Wordファイルを扱っていて「だんだん重くなっていく」と感じたことはないだろうか。特に、代々引き継がれてきたファイルほど、修正や保存が重くなる、と感じたことはないだろうか?あなたのその感覚は正しい。長い間修正され続け、重くなったWordファイルを、個人的に「疲れたファイル」と呼んでいる。
ぜひリンク先をご一読いただきたいですが、この記事で特に注目したいのは
という事実です。つまり同僚の文句は
🤔 Mac版のWordで修正しているから徐々に重くなっているのでは?
という可能性があります!
しかし、上述の記事は2018年の投稿、すなわち6年も昔の情報です。
本記事ではWordファイルの内部構造を眺めながら、実際にバグが修正されているかを確認してみました✍️
先に結論を言うと、不具合は修正されていました。
Wordさんはもうお疲れではありません!
調査
検証に使用した Word は今日 (2024/01/29) 時点で App Store で配信している最新版 (v16.81) です。
その他、実行環境については以下にまとめておきます。
実行環境とマシンの情報
$ 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ファイルの中身を見る
それでは調査していきましょう。まずは適当な文章を記入したファイルを保存します。
余計な修正をすると差分を保存されてしまいそうなので、事前にコピーしておいたプレーンテキストをペーストして即座に保存しました。
保存された.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のバージョンに更新が入ったのでしょうか…?
少しだけ改変するとどのように変化するか
以上の情報を踏まえた上で、適当な文字!
を挟んでから保存してみます。
改めて./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>
ここから分かる変化は、
-
textId
が更新されている -
<w:proofErr w:type="gramStart"/>
属性が追加されている -
w:rsidRPr=001677CA
が複数に分割され、その内部にw:rsidR="00010F2E
が割り込んでいる
1.のtextId
は、その要素内に更新が入ると新規に発行される仕様ということでしょう。
次に、スクリーンショット中の下線部からわかるように、2.は文法チェックの警告情報が付与されたためです。これらもxml内で管理されるわけですね。
3.は更新履歴に該当しており、w:rsidR="00010F2E
と<w:proofErr w:type="gramStart"/>
が割り込んだことにより分割されている、と言えそうです。
2行が削除され16行が追加されているわけですから、これを繰り返せば次第にパースが大変になっていくのは明白ですね😲
もとに戻すとどうなるか?
しかし、これらはWordの挙動を実現するために必要な情報です。大切なのは
- 差分情報がない状態、すなわち元のリビジョンに戻したときに
- それまでの変更履歴がちゃんと削除されて断片化しない
ということです。次にこれを確認しましょう。
もう一度Wordを開き、!
を削除してから保存します。
この状態で./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