🐕

[rubyXL]Rubyでxlsxファイルを読み込み・出力してみる

2021/10/25に公開

業務で使ったところをかいつまんでまとめていきます。

使ったgemはこちら。
https://github.com/weshatheleopard/rubyXL
バージョンは3.4.18
xlsx系のgemをざっと調べた感じ、読み込み・出力と両対応しているものでポピュラーそうだったので。

書き出し

インスタンスを作成して、書き込みをする。

workbook = RubyXL::Workbook.new
workbook.write("path/to/desired/Excel/file.xlsx")

https://github.com/weshatheleopard/rubyXL#creating-a-new-workbook-
https://github.com/weshatheleopard/rubyXL#io-

データ入力

シートを取得してそのシートにセルを追加することでデータを入力することができます。
workbookインスタンス作成時にデフォルトでシートが一つ存在しているのでそのシートを取得して、行と列を指定して'A1'を入力します。

worksheet = workbook[0]
worksheet.add_cell(0, 0, 'A1')

https://github.com/weshatheleopard/rubyXL#adding-cells-

折返し

以下のように長文を入力したときに

workbook = RubyXL::Workbook.new
worksheet = workbook[0]
worksheet.add_cell(0, 0, 'A')
worksheet.add_cell(0, 1, 'B')
worksheet.add_cell(0, 2, 'C')

worksheet.add_cell(1, 0, 'A1')
worksheet.add_cell(1, 1, 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもも')

workbook.write("sample.xlsx")

このように横に長くなるのでそれを折り返したくなりました。

Readmeを読んだ感じ、cell.change_text_wrap(true) でいけそうです。
https://github.com/weshatheleopard/rubyXL#modifying-cell-format-

add_cellの返り値がCellクラスなので、

worksheet
  .add_cell(1, 1, 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもも')
  .change_text_wrap(true)

とやってみるが以下のエラー。

NoMethodError: undefined method `change_text_wrap' for #<RubyXL::Cell(1,1): "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもも", datatype="str", style_index=0>

change_text_wrapメソッドがないと言われる。

結論から言うと、

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

を追加する必要があります。
https://github.com/weshatheleopard/rubyXL#convenience-methods-

change_text_wrapメソッドがどこで定義されているかコードを探して見ると、

# lib/rubyXL/convenience_methods/cell.rb 
module RubyXL
  module CellConvenienceMethods
    def change_text_wrap(wrap = false)
      validate_worksheet
      self.style_index = workbook.modify_alignment(self.style_index) { |a| a.wrap_text = wrap }
    end
  end
end

https://github.com/weshatheleopard/rubyXL/blob/master/lib/rubyXL/convenience_methods/cell.rb#L52

CellConvenienceMethodsモジュールはデフォルトでは読み込まれてないので、必要なら各自でincludeして使うみたいです。

require 'rubyXL/convenience_methods/cell

して再度試してみると今度は以下のエラー。

undefined method `modify_alignment' for #<RubyXL::Workbook:0x000055fbb8abb918 省略

modify_alignmentメソッドを探してみると
https://github.com/weshatheleopard/rubyXL/blob/cc332cace906f96d9dd3a685f241b93e02f3bb94/lib/rubyXL/convenience_methods/workbook.rb#L58
にあるので、

require 'rubyXL/convenience_methods/workbook'

も必要ということでした。

これで無事折返しが設定できました。

require 'rubyXL/convenience_methods/cell'
require 'rubyXL/convenience_methods/workbook'
    
workbook = RubyXL::Workbook.new
worksheet = workbook[0]

worksheet.add_cell(0, 0, 'A')
worksheet.add_cell(0, 1, 'B')
worksheet.add_cell(0, 2, 'C')

worksheet.add_cell(1, 0, 'A1')
worksheet
  .add_cell(1, 1, 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもも')
  .change_text_wrap(true)

workbook.write("sample.xlsx")

列の横幅

列の横幅指定はchange_column_widthメソッド。
B列の横幅を指定してみます。

require 'rubyXL/convenience_methods/worksheet'

が必要です。

require 'rubyXL/convenience_methods/cell'
require 'rubyXL/convenience_methods/workbook'
require 'rubyXL/convenience_methods/worksheet'
    
workbook = RubyXL::Workbook.new
worksheet = workbook[0]

worksheet.change_column_width(1, 30)

worksheet.add_cell(0, 0, 'A')
worksheet.add_cell(0, 1, 'B')
worksheet.add_cell(0, 2, 'C')

worksheet.add_cell(1, 0, 'A1')
worksheet
  .add_cell(1, 1, 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもも')
  .change_text_wrap(true)

workbook.write("sample.xlsx")

https://github.com/weshatheleopard/rubyXL#changing-column-width-

文字を上端にそろえる

セル内の文字を上端に揃えたくなりました。
その場合はchange_row_vertical_alignmentメソッド。
https://github.com/weshatheleopard/rubyXL#vertical-
セルのみ指定や、行での指定もできます。

今回はA, B, C列を上端揃えに。

require 'rubyXL/convenience_methods/cell'
require 'rubyXL/convenience_methods/workbook'
require 'rubyXL/convenience_methods/worksheet'
    
workbook = RubyXL::Workbook.new
worksheet = workbook[0]

worksheet.change_row_vertical_alignment(0, 'top')
worksheet.change_row_vertical_alignment(1, 'top')
worksheet.change_row_vertical_alignment(2, 'top')

worksheet.change_column_width(1, 30)

worksheet.add_cell(0, 0, 'A')
worksheet.add_cell(0, 1, 'B')
worksheet.add_cell(0, 2, 'C')

worksheet.add_cell(1, 0, 'A1')
worksheet
  .add_cell(1, 1, 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもも')
  .change_text_wrap(true)

workbook.write("sample.xlsx")


top以外はどう指定するんだろうとコードを追ってみると、ここに使える文字列が定義してありました。
top center bottom justify distributedが使えるよう。
https://github.com/weshatheleopard/rubyXL/blob/cc332cace906f96d9dd3a685f241b93e02f3bb94/lib/rubyXL/objects/simple_types.rb#L13

編集不可(ロック)

それようのメソッドはない模様。
https://github.com/weshatheleopard/rubyXL/issues/320
これでいけるらしい。
が、少し試してみたがロックできず。。

読みこみ

既存ファイルの読み込みは、

workbook = RubyXL::Parser.parse("path/to/Excel/file.xlsx")

https://github.com/weshatheleopard/rubyXL#io-

workbookのインスタンスが生成されるので、あとはこれまで書いてきたようにデータの追加編集などできて保存できます。

その他

出力する文章に改行以外の制御文字が含まれていると処理がスキップされました。
エラーは発生せず正常に終了するが、該当の行以降は出力されていない。
出力時に

text.gsub(/[[:cntrl:]]/, ''))

として制御文字を削除することで対応しました。

Discussion