Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails: pandocによるdocx(Microsoft Word)ファイルの生成

docxファイルの生成・出力機能を開発する機会があったので、 pandoc-ruby を利用した実装方法について説明します。

なお、開発および動作確認はMacOS環境で行っています。
環境次第では本記事の内容が完全に再現できないかもしれません。ご了承ください。

gemについて

pandoc というドキュメントフォーマット変換のプログラムがあり、 pandoc-ruby はそのRuby用ラッパーライブラリです。
このライブラリを利用する場合、まず出力内容を表すファイルや文字列を用意して、それを .docx に変換する流れで実装していきます。

他のライブラリも探したのですが、GitHubのスター数で pandoc-ruby に匹敵する代替案が見つからず、このgemを採用しました。

準備

コントローラーで format.docx のように記述したいので、MIME typeを登録しておきます。

# config/initializers/mime_types.rb
Mime::Type.register "application/vnd.openxmlformats-officedocument.wordprocessingml.document", :docx

pandoc-ruby が利用する pandoc も必要なので、あらかじめインストールしておきます。

# Dockerfile
RUN apt install -yq\
    pandoc\
    ...

Gemfileには pandoc-ruby を追加します。

# Gemfile
gem "pandoc-ruby"

使用方法

例として、GETリクエストでファイルダウンロードを可能にしたい場合、以下のように実装します。

# audios_controller.rb
def show
  respond_to do |format|
    format.docx do
      str = render_to_string "audios/show.docx.erb", locals: { audio: @audio }
      document = PandocRuby.convert(str, to: :docx)
      send_data document, filename: "audio_#{@audio.id}.docx", mime_type: Mime["docx"], disposition: :attachment
    end
  end
end

docxファイルは動的な内容にしたいので、変数埋込可能なerbテンプレートを利用して出力内容を表しています。
また、 pandoc入力内容をデフォルトでMarkdownとして解釈します。そのため、 PandocRuby.convert の前に render_to_string を呼び出し、 erbテンプレートの内容をHTML文字列(Markdownとして解釈可能な文字列)に変換しています。

直接確認していませんが、 pandoc が扱えるものであれば、他のフォーマット同士でも PandocRuby.convert:from / :to の指定・変換ができるはずです。


erbファイルは以下のようにしています。

<!-- audios/show.docx.erb -->
<% audio.transcripts.each do |transcript| %>
  <%= transcript.started_at.strftime("%X") %>
  <%= "" %>
  <%= transcript.content %>
  <%= "" %>
  <br>
  <%= "" %>
<% end %>

このテンプレートで、以下のようなdocxファイルを生成しています。

改行 / 改段落

注意点として、Markdown / docxには改行と改段落があり、見た目も異なります。

改行 改段落

erbでは以下のように記述しています。

<!-- 改行 -->
<%= "\\" %>

<!-- 改段落 -->
<%= "" %>

空の段落

以下のように、内容が空の段落を挿入したいとします。

<%= "" %> を連続させる方法が思いつきますが、これだと段落が1つにまとまり、空の段落は挿入されません。

<%= transcript.content %>
<%= "" %>
<%= "" %>

オフィシャルな解説が見つからなかったのですが、検証した限りでは「空の行 + 改段落」の組み合わせで空の段落を挿入できるようです。
自分は以下のように <br> を挿入することで解決しました。

<%= transcript.content %>
<%= "" %>
<br>
<%= "" %>

簡単な内容でよければ、この程度の作業量でdocxファイルを生成することができます。



CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。