niszetの日記

細かい情報を載せていくブログ

R MarkdownでPandocからdocxを作成をする際にsvgを取り込むのは現状難しそう。

調べたことのまとめ

Pandocユーザー会の方でWordにsvgを入れたいといった話があったのでR Markdownなら出来ないだろうかと思って調べた結果。現時点では難しい(Pandoc側の問題で)ので、対策を考える必要がある。

R Markdown側でsvgを作成する方法

これは下記のSOにあるように、チャンクオプションでdev='svg'とすればよい。

stackoverflow.com

{r pressure, dev='svg}

作成されたsvgファイルを確認したければ、YAMLフロントマターに下記のように書いて、中間生成物である(Pandocに渡す)Markdownファイルを残すようにすればよい。この時に画像ファイルも一式残ることになる。

output:
  word_document:
    keep_md: TRUE

docx側で調べたこと

self--containedを指定するとsvgファイルそのものが作成されていない気がする。あとで再調査。それ以外はsvgファイル自体は自身に取り込まれていると思うのだが、docx側でうまく参照できてないような出力になる(画像のある場所に[x]読み込めませんのような表示)

    pandoc_args: 
      ['--self-contained']

Word側で図を差し替えようとすると、svgを選択した場合は1回目は画像が表示されず([x]は消える)同じ操作を2回やると画像が表示された。pngの場合は1回で出来る。1回目の状態で正しく反映されるかは未調査。

なお、Pandocで生成したdocxは互換モードになっているので一旦変更を行う必要があるが、この時に<?xml version="1.0" encoding="UTF-8" standalone="yes"?>になるわけではないと思うので、standaloneがどこでついているのか謎…。

svgを手で別途追加したときもちょっと挙動が違う。この辺りはもう一度まとめないと何が何やらである。

svg用のタグは別にありそう。

手でsvgを入れたWordファイルの場合、タグが下記のようになっている。

<asvg:svgBlip xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main" r:embed="rId9"/>

pngなどの場合は下記のようになる。

<a:blip r:embed="rId9"/> 

このrId9の指すリンク先はdocument.xml.relsに書かれている。しかし、このpngで使われているタグのリンク先をsvgに変えても表示されない(というよりも開くとエラーとなる)

このsvg用と思われるタグで検索すると下記の掲示板があった。このやり取りが一番参考になりそう。まだ読み途中。

apache-poi.1045710.n5.nabble.com

このリンク先の仕様書を読んでもよくわからない。このタグを使う方法はわかったけど読まなくてもわかったし・・・

[http://interoperability.blob.core.windows.net/files/MS-ODRAWXML/[MS-ODRAWXML].pdf:embed:cite]

Pandocのdocx writerの方を見てみても、上記のタグがないような(まだ探し途中だが)ので、svg対応が出来ていないかも。 http://hackage.haskell.org/package/pandoc-2.3.1/docs/src/Text.Pandoc.Writers.Docx.html#local-6989586621680791699

処理分けられれば良さそうだなという気がするので、上記のa:blipに置き換えるところでsvg用のタグに置き換えてビルドすれば出来るかな。いずれやってみる(Haskell環境がない

wmfについて

R Markdownで先のチャンクオプションのdevの部分を下記のように書き換えることでwmfファイルに置き換えることが出来る。

{r pressure, dev='win.metafile'}

ただし、この場合は余白が無駄に生成されているようで、pngの図と等価(形状的に)ならない。そのため、こちらも現状ではおすすめできないことになる。

ほか

こういうのもSO.jpにあった。apache POIの方が情報が集まりやすいだろうか?そんなことはないか…。

ja.stackoverflow.com

とりあえず、現状ではPandocでsvgを取り扱うのは難しそうかなぁ…。生成したdocxを書き換えるか、filter作るか…と思ったけどwriterが対応していなければfilter作っても意味ないか…。

追記

よくよく見てみると、a:blip の中にasvg:svgBlip があった。先のpdfの「1.3.3 Pictures」を見ると、後方互換性のためにpng表示をするといったことが書かれていたので、その処理だろう。つまり、svgを差し込むときはコンパチなpngを準備して、下記の構造を持たせたタグにする必要があるということになる。これはちょっと面倒くさそうですね。

いずれにしてもsvgの場合はタグをわけなくてはいけないことには変わりないのですが…。

<pic:blipFill>
<a:blip r:embed="rId8">
<a:extLst>
<a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
<a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/>
</a:ext>
<a:ext uri="{96DAC541-7B7A-43D3-8B79-37D633B846F1}">
<asvg:svgBlip xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main" r:embed="rId9"/>
</a:ext>
</a:extLst>
</a:blip>
<a:stretch>
<a:fillRect/>
</a:stretch>
</pic:blipFill>

追記の追記

本家でもPR出ているので、うーむ対応されなさそう。

github.com

とりあえずpng刺しておいて、あとからsvgに置き換えるってのが出来るのかを手で確認してRで実装かな…。