MSWordのdocxをshellでなんとかする

初めまして 前職では肩書きが3回変わりましたレイラです。

この記事はex-handslab Advent Calendar 2018の10日目になっています。

皆様は公の機関に出すために雑でもいいからdocxでファイルが欲しいみたいな事象に出くわしたことはないでしょうか?いや、ない。(反語)

そんな需要のないことも時にはありますが、(バッチ処理とかで)きっとshellだけでやりたくなる日もあるでしょう。

モチベーション

参考文献にも書かれていますが、MSWordのdocxはxmlの集合体をzipで固めたものです。

また、word/document.xmlからwordのテキストが抽出できることもわかっています。

つまりdocument.xmlを編集すればdocxの編集ができるということが推測できます。

ワンチャンありそうだったのでやってみました。

作業手順

  • アンカが入ったテンプレート用Wordを作成
  • unzipで解体
  • 解体先の/word/document2.xmlの置換
  • zipで圧縮
  • 拡張子をdocxに戻す

テンプレート作成

まずはテンプレートを作成するのですが、お手持ちのMacにMSOfficeが存在しなかったためOnedriveで作成します。

f:id:leyline:20181207171628p:plain
テンプレート例
]

###Title######Text###がアンカーです。 置換する際に別の単語に引っかからなさそうな単語なら何でも大丈夫です。

f:id:leyline:20181207171731p:plain
ダウンロード

ファイル->コピーをダウンロードなどで手元まで持って来ましょう 以後はダウンロードしたdocxファイルをbase.docxとします。

unzipで解体

サブタイ通りです unzip -d olddocx base.docx すると

tree olddocx/ 
olddocx/
├── [Content_Types].xml
├── _rels
├── docProps
│   ├── app.xml
│   └── core.xml
└── word
    ├── _rels
    │   └── document2.xml.rels
    ├── document2.xml
    ├── fontTable.xml
    ├── settings.xml
    ├── styles.xml
    ├── theme
    │   └── theme1.xml
    └── webSettings.xml

このようなディレクトリ群が生成されます。

Onedriveで作成したdocxだとdocument.xmlではなくdocument2.xmlになるようです(よくわかっていない

テキストの置換

sed \
-e "s/###Title###/${Title}/"    \
-e "s/###Text###/${Text}/"      \
./olddocx/word/document2.xml > ./olddocx/word/new_document2.xml
mv -f ./olddocx/word/new_document2.xml ./olddocx/word/document2.xml

Title変数とText変数に入ったものをタイトルの部分とテキストの部分に置いています。 改行が入るものであれば適宜いい感じにしてください。

zip化 && リネーム

cd olddocx
zip -r newdocx ./
cd ../
mv newdocx.zip newdocx.docx

これで完了です。

あとがき

外部ライブラリやコマンドを使用しない点はとても良いし、さらなる発展性がありそうだなと思います。

いつの時代になってもテンプレートからの展開は腐らないと思うので、来たるべき時に思い出してください。

参考文献

シェルスクリプトでWordの文章を扱う技術 | コンパス