Ruby で Excel ファイルを作る

お久しぶりです。masm11 です。随分時間があいてしまいました。

以前、Python で Excel ファイルを作成する方法について書きました。 しかし弊社はやはり Ruby がメインなので、今回は Ruby で作成する方法について 紹介したいと思います。

Ruby で Excel ファイルを扱える gem にはいくつかあるようです。

  • Win32OLE
  • WrapExcel
  • Spreadsheet
  • Roo
  • Axlsx

(https://qiita.com/damassima/items/1b791ba90459ef0534fe より)

たくさんありますね。しかし今回は .xlsx ファイルを Linux で(かつ無料で)作成したいので、

  • rubyXL

を使うことにします。

gem のインストール

Rails で使いたいので、Gemfile に以下のように書きます。

gem 'rubyXL', '~> 3.4.3'

そして、いつもどおり、

bundle

です。

Rails でなくただの Ruby プログラムで使いたい場合は、

gem install rubyXL -v '~> 3.4.3'

ですね。

require する

rubyXL にはいろいろな便利メソッドがありますが、 rubyXL 3.4.0 以降では、メモリ使用量を削減するため、これらの便利なメソッドを使うには明示的に require してやる必要があります。

あとで set_number_formatchange_contents メソッドを使いたいので、 ここでは以下のようにします。

require 'rubyXL/convenience_methods/cell'
require 'rubyXL/convenience_methods/workbook'

Rails の場合でも必要です。

その他に require できるものについては、本家に書いてあります。

使う

require したら、コード本体を書いてみましょう。

まずは、Workbook を作成し、その中のシートを取得します。

book = RubyXL::Workbook.new
sheet = book[0]

ではこのシートに値をセットしていきます。

A1 セルに foo を入力するには以下のようにします。

sheet.add_cell(0, 0, 'foo')

簡単ですね。

A2 セルに数値の 2 を入力するには以下のようにします。

sheet.add_cell(1, 0, 2)

'2' と文字列にしてしまうと、勝手に '2 になってしまうので、型には注意してください。 Excel のいつものお約束ですね。

なお、add_cell の引数は、1つめが縦の位置、2つめが横の位置で、どちらも 0 から始まります。

日付の場合は少し特殊です。add_cell メソッドが Date 型に対応していないのです。

A3 セルに日付の 2019/06/10 を入力するには、以下のようにします。

c = sheet.add_cell(2, 0, 0)
c.change_contents(Date.parse('2019/06/10'))
c.set_number_format('yyyy/mm/dd')

1行めでセルに数値型の 0 をセットしています。これでこのセルは数値型になります。 そして2行めで日付をセットしています。change_contents メソッドは Date 型に対応しています。 最後に3行めで日付の表示形式をセットします。

ここで、上に書いた require をしていない場合、以下のエラーになります。

./test.rb:14:in `<main>': undefined method `change_contents' for #<RubyXL::Cell(2,0): 0, datatype=nil, style_index=0> (NoMethodError)

保存する

ファイルに保存します。

book.write('foo.xlsx')

この foo.xlsx を開くと、以下のようになります。

f:id:masm11:20190610224818p:plain

Rails を使った Web サービスなどでは、小さいファイルなら、ファイルに保存するよりメモリ中に作ってくれた方が便利なこともよくあります。 その場合は、以下のようにします。

data = book.stream.read

まとめ

以上、Ruby で簡単に Excel ファイルを作ってみました。

Python で作れることを知った時には、「きっと Ruby でもできるはず!」と思いました。 本当にあるんですね… 便利な世の中です。

ではまた。