jrubyからApache POIを使う超手抜きモジュール

rubyからExcelファイルを読み書きするのは、Spreadsheet(pure ruby)とかwin32oleを使う方法がある。
たまたま、とあるExcelテンプレートファイルを読んで、ごにょごにょ編集して、別ファイルに出力するという機会があった。
この処理をLinux上で動かしたかったため、Spreadsheetを試してみたが、運悪くそのテンプレートファイルには
シートの保護がなされていて、出力したExcelファイルがどうしても壊れてしまう。
このへんは、Spreadsheetが対応できていないようだ。

ほかに似たようなライブラリがないか探してみたが、どうにも見つからない。
仕方がないので、実績のあるApache POIをjrubyから使ってみることにした。
さすがにPOI。難なくやりたいことができてしまった。

それにしてもこのPOI、値をセットするときは型を気にする必要はないが、
取得するときはいちいちセルの型を調べないといけないのがちょっと面倒…

poi_workbook.rb:

require 'java'
require './poi-3.7-20101029.jar'
require './poi-ooxml-3.7-20101029.jar'

java_import java.io.FileInputStream
java_import java.io.FileOutputStream
java_import org.apache.poi.ss.usermodel.WorkbookFactory
java_import org.apache.poi.ss.usermodel.DataFormatter

class Workbook

  def initialize(path)
    @fis = FileInputStream.new(path)
    @book = WorkbookFactory::create(@fis)
  end

  def self.open(path, &block)
    book = Workbook.new(path)
    return book unless block_given?
    yield book
    ensure
      book.close
  end

  def write(path)
    fos = FileOutputStream.new(path)
    @book.write(fos)
    ensure
      fos.close
  end

  def close
    @fis.close
  end

  def select_sheet_at(index)
    @sheet = @book.get_sheet_at(index)
    @sheet.set_force_formula_recalculation(true)
  end

  def []=(row_idx, col_idx, value)
    @sheet.create_row(row_idx) if @sheet.get_row(row_idx).nil?
    row = @sheet.get_row(row_idx)
    row.create_cell(col_idx) if row.get_cell(col_idx).nil?
    row.get_cell(col_idx).set_cell_value(value)
  end

  def [](row, col)
    return nil if (row = @sheet.get_row(row)).nil? or (cell = row.get_cell(col)).nil?
    return DataFormatter.new.format_cell_value(cell)
  end
end

if __FILE__ == $0
  # sample usage
  Workbook.open('template.xls') do |book|
    book.select_sheet_at(0)
    book[0, 0] = book[0, 0] + ' new value'
    book.write('new.xls')
  end
end

※細々としたセルの値に対応していません。