ill-identified diary

所属組織の見解などとは一切関係なく小難しい話しかしません

[R Markdown] から [Word] へエクスポートするときのテンプレート (with officedown)

この記事は最終更新日から3年以上が経過しています

概要

概要 デフォルトの word_document よりもう少し機能の豊富な Word 用テンプレートを提案する.

初めに

先日の Tokyo.R で意外と Word へのエクスポートを望む人が多いと分かったのでテンプレートパッケージを作ってみた.

ただし, 以前から作っている rmdja は (1) 日本語を含む PDF 文書出力時の煩雑な初期設定を省くことを主眼に置き, (2) かつ PDF と HTML との間にある程度スタイルの一貫性をもたせることをモチベーションにしているので, いまのところ Word フォーマットを追加するつもりはない.

まず念の為補足しておくと, rmarkdown 本体にも出力フォーマット word_document があり, 新規作成時に選択できる基本テンプレートの1つに入っている*1. 基本的なことはこれでできてしまうが, もう少し凝ったことをしたい, 出力の綺麗さにこだわりたい, という人のために少しカスタマイズしたテンプレートパッケージ wordja を作った. 本当にテンプレートだけであり, 実質的に officedown*2 パッケージのテンプレートを日本語にしてちょっといじってるだけといっていい.

動作確認は以下の3種類の環境で行った.

  • Windows 10 + Word 16.0.13091 (2103)

  • Ubuntu 20.04 + Libre Office 6.4.7.2

  • Mac Catalina + Word 1648 (2104)

出力例をまずは見せろという人はここからダウンロードするのが手っ取り早い.

f:id:ill-identified:20210422223704p:plain
出力例

Libre Office は概ねうまくいくがレイアウトが一部狂うことがあり, 手動調整が欠かせないだろう. Libre Office との完全互換はややこしすぎたので諦めた*3.

使い方

必要パッケージとインストール

必要なパッケージは以下の通り. 基本的にはこの wordja のインストール時に一緒にインストールされるはず.

  • officedown (>= 0.2.2)

  • ragg (>= 1.1.0, Mac ユーザーのみ必須, それ以外は「インストール推奨」)

  • おそらく rmarkdown もなるべく最新バージョンにしたほうがよい

以下は必須ではないが, あると良いかもしれない

  • bookdown

  • redoc (現在開発中止)

まずは wordja をインストールする. どうしてもインストールしたくないならこのページの最後に書いたテンプレートをコピペして使う (どちらにせよ上記のパッケージは必要).

GitHub - Gedevan-Aleksizde/wordja: R Markdown の Word 用テンプレート

新規作成

以下のテンプレートをコピペする. または, パッケージの体裁でも作った*4ので, インストールしてテンプレートから選択という手もある. 慣れてくればオプション項目が大量にあるテンプレートが邪魔になると思うので, パッケージのほうにはミニマルバージョンも用意した.

相互参照は bookdown と同様に, チャンクラベルやセクションラベルに対して, \@ref(fig:LABEL),\@ref(tab:LABEL) , \@ref(LABEL) と書くことでできる. さらに表を掲載する時は knitr::kable() を使わずとも自動整形される. さらにグラフの fig.cap チャンクオプションのように, 表に対しても tab.cap チャンクオプションが定義されているので, これで表のキャプションを指定する. flextable パッケージにも対応している (というか kableExtra 等はたぶんうまく動作しない).

実態として officedown パッケージの機能をそのまま使っているだけなので, 詳しい機能はパッケージの公式ドキュメントか Officeverse を見て欲しい.

カスタマイズ

ユーザー定義のスタイルを使うには, 主に YAML メタデータを使う. 各所に style というフィールドがあるが, これがそれぞれのブロック要素のスタイル名に対応している.

注意点

わりと致命的な問題点: Windows かつ言語を日本語に設定していると相互参照が使えないことがある. いちおう現状での回避方法は提示されている*5. Rmd ファイルで同じ行に相互参照の記号と日本語が含まれていなければ良いので, 改行してしまうというもの (具体的にはテンプレートの書き方を参考にしてほしい). MacLinux などローカルなマルチバイト文字コードを使わない OS ではおそらくこの問題は発生しない.

ちょっと厄介な問題点: Mac の場合のみ, グラフに含まれた日本語が文字化けする. dev=’ragg_png’ を指定することで回避できるが, 一方で Mac 以外の環境では逆にエラーが出ることがある. よって複数種類のOSでも動作するように設定すると少し大変である. テンプレートでは応急処置的な設定をしておいた.

解説

offficedown パッケージはデフォルトのフォーマットにいろいろな機能を追加している. officedown の仕様はやや特殊で, word_document/bookdown::word_document2 でうまく出力できていた Rmd をそのまま同じように出力できるとは限らない. これまでの Rmd を移植するのはそれなりに R Markdown の仕組みに詳しくないと難しいと思うので, これから新しく作る文書だけ適用するとよいだろう. 例えば以下が特に違う

  • 相互参照の実装・構文が異なる (ただし今回のテンプレートは擬似的に bookdown と同じようにできるよう設定している)

  • 表の出力が異なる

    • knitr::kable() などを使うとかえってレイアウトが崩れやすい

    • データフレームを直接表示させるだけでもよい

  • グラフィックデバイスは基本的に変更しない想定

相互参照機能は bookdown パッケージでも提供され, rmdja でもその機能を流用しているが, officedown の相互参照の構文はこれとは違う. officeverse に書いてあるように, チャンクオプションをいくつも付けねばならない. しかしそれは面倒なので, knitr のフック機能によって wordja ではチャンクラベルで参照できるようにしてみた (つまり bookdown パッケージと同じ使い方). これは上記テンプレートの最初のチャンクで定義されている. また, officedown も同チャンクで読み込んでいるが, これは Word に表を正常に表示するのに必要らしいので注意.

しかし応急処置なのでうまく行かない場合は officedown 本来の構文を使ってみて欲しいし, 不要ならチャンクごと消しても構わない.

rmdja パッケージでは PDF/HTML 出力時のこういった煩雑な初期設定をすべて出力フォーマット関数の中に埋め込み, ユーザーは気にせず使うことができるように作っているが, 私は Word をほぼ使わないのでいまのところ保守するモチベーションがない.

簡単なテンプレート

この記事を描いた時点で wordja と同じ設定.

---
title: "日本語Word文書へエクスポート"
author: "ill-identified"
date: "`r format(Sys.Date(), format='%Y/%m/%d')`"
output:
  officedown::rdocx_document:
    toc: no
    plots:
      caption:
        pre: "図"
    tables:
      caption:
        pre: "表"
---

```{r setup-officedown, include=F}
knitr::opts_hooks$set(
  label = function(options){
    if(is.null(options$fig.id)) options$fig.id <- options$label
    if(is.null(options$tab.id)) options$tab.id <- options$label
    options
  }
)
knitr::opts_chunk$set(
  echo = TRUE,
  fig.cap = TRUE,
  if(Sys.info()["sysname"] %in% c("Windows", "Darwin") && "ragg" %in% installed.packages() && packageVersion("ragg") > 1.1) 'ragg_png' else 'png'
  )
library(officedown)
library(officer)

fp <- fp_par(
  text.align = "center", 
  padding.bottom = 20, padding.top = 120, 
  border.bottom = fp_border())

ft <- fp_text(shading.color='#EFEFEF', bold = TRUE)
```

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = T)
```

ここから本文


*1:ここを見れば分かるように: https://rpubs.com/ktgrstsh/755893

*2:ところでこれを書いてから気づいたが officedown パッケージは『R Markdown クックブック』の8章 https://gedevan-aleksizde.github.io/rmarkdown-cookbook/word.html 以外で紹介している日本語のページがほぼ見つからない...

*3:私の環境では, 目次やセクション見出しへのリンクがうまくいかなかった.

*4:いまのところ rmdja で対応する予定はない

*5:https://github.com/davidgohel/officedown/issues/37