著者:こしば としあき
主に業務の分野で頻繁に使われる、「Microsoft Excel」(以下、Excel)。それを操作するためのスクリプト言語として Ruby を活用する事ができます。
今回は、Ruby を使って Excel を扱う為の基本的な部分を、細かい実装の理屈を抜きにして即物的に解説します。
この記事で解説する事を行うには、Windows 上で、Microsoft Excel と Ruby が動く環境が必要です。Ruby の入手とインストールについては、FirstStepRuby を参照してください。
サンプルコードの動作は下記環境で確認しております。
なお、コードのエンコーディングはシフト JIS を用いて動作確認を行いました。同じくシフト JIS でサンプルコードを試す場合は、ソースファイルの先頭で下記ようにエンコーディング指定を行ってください。使っている Ruby が 1.8 系でも 1.9 系でもこれで動作します。
#! ruby -Ks
# -*- coding: sjis -*-
能書きはいいから Excel を楽に操作する方法を知りたいあなた!
最低限下記のコードがあれば、Excel を開いてシート上のデータを取り出すことができます。
require 'win32ole'
app = WIN32OLE.new('Excel.Application')
book = app.Workbooks.Open(app.GetOpenFilename)
#使っているワークシート範囲を一行ずつ取り出す
for row in book.ActiveSheet.UsedRange.Rows do
#取り出した行から、セルを一つづつ取り出す
for cell in row.Columns do
p cell.Address
p cell.Value
p '-------'
end
end
book.close(false)
app.quit
このコードでは、以下の事を行っています。
動作サンプルは以下の通りです。
Elysion | Roman | Moira |
2004,2005 | 2006 | 2008 |
"$A$1"
"Elysion"
"-------"
"$B$1"
"Roman"
"-------"
"$C$1"
"Moira"
"-------"
"$A$2"
20042005.0
"-------"
"$B$2"
2006.0
"-------"
"$C$2"
2008.0
"-------"
結構 VBA と似たような単語が使われているなと思われたかもしれませんが、まさにそのとおりです。
何故なら多くが Excel のオブジェクトであるからです。同様の事を行う VBA のコードと見比べてみましょう。
Set book = Workbooks.Open(Application.GetOpenFilename)
'使っているワークシート範囲を一行ずつ取り出す
For Each row In book.ActiveSheet.UsedRange.Rows
'取り出した行から、セルを一つづつ取り出す
For Each cell In row.Columns
Debug.Print cell.Address
Debug.Print cell.Value
Debug.Print "-------"
Next cell
Next row
book.Close False
気付きましたでしょうか、Excel を操作する部分は全く同じなのです。
ただ、異なる点としては、下記 3 点があります。
Ruby は VBA のようにプリミティブとオブジェクトを区別せず、すべてオブジェクトとして扱います。よって、オブジェクトだから set ステートメントを使う、プリミティブだからそのまま代入するといった面倒な使い分けが必要ありません。
本来 Excel の VBA では、Excel のインスタンスは Application オブジェクトとして生成済みです。Ruby では標準添付ライブラリの Win32OLE クラスを用いた下記のコードで Excel のインスタンスを生成する必要があります。
app = WIN32OLE.new('Excel.Application')
なお上記コードは、VBS で利用する下記のコードと同じ意味です。
Set app = CreateObject("Excel.Application")
本来 Excel の VBA では、Applicaion オブジェクトや ActiveWorkbook オブジェクトなど、いくつかのオブジェクトの名前を省略できます。Ruby では省略できないので、必ずどのオブジェクトを用いるのかを明示する必要があります。
最近は様々な業務を Web サーバと Web ブラウザによって行えるようになっています。ソフトウェア開発現場でもその例に洩れず、BTS、Wiki など Web アプリケーションが、広く普及しています。
しかし、現在もなお業務に関する多くのデータは、オフィススイートによって作成・編集され、人々の間を飛び回っています。
オフィススイートはいくつものアプリケーションで構成されていますが、日本では表計算ツールの Excel が一番汎用的に使われています。例えば、一覧表、報告書、処理設計書、画面イメージ設計、チラシ、さまざまなものが Excel で作られています。
そんな Excel の操作や処理を簡便にするためには、ご存じの通り VBA (Visual Basic for Applications) を用います。ユーザ数も多く利用頻度も高い、一番使われているプログラム言語&開発環境ではないでしょうか。そんな VBA は、長い期間使われ続けているので様々なノウハウがたまっている反面、不満やイライラも多くたまってきていると思います。
そこで、VBA の代わりに Ruby を使うことで、不満やイライラを解消しつつ、Excel を扱う上でのノウハウはそのままに、さらに便利かつ強力に Excel を処理できます。
また、一応 Ruby 勉強してるけど・Ruby に興味があるけど、いまいち何に使えばいいか分からないと悩みを抱えている VBA 使いのあなたにとって、これを機会に Ruby を使えるようになると、Excel の仕事を楽に片付けつつ Ruby を使えるようになり、一石二鳥の効果があります。
さて、VBA ではこのようなコードがよく出てきます。
buf = Cells(i, 1).Value & _
"や" & _
Cells(i, 2).Value & _
"は、我々の業界ではご褒美です。"
このようなコードによって下記のような問題が引き起こされます。
これらの問題のせいで、腹立たしい思いをした人は多いと思います。勿論、筆者もその一人です。
実は Ruby では、同じ意図のコードをリテラルの式展開を使ってシンプルに記述できます。
buf = "#{app.Cells(i, 1).Value}や#{app.Cells(i, 2).Value}は、我々の業界ではご褒美です。"
また、ソースコードの自動生成など、複数行にわたる文字列を出力する場合、VBA で実現しようとするととんでもないコードになってしまいます。
例えば、Excel 上のデータを用いて、下記のようなクラスのスケルトンを作りたい場合を考えます。
package AAAAA;
class BBBBB {
public CCCCC DDDDD() {
//TODO: method implement
;
;
;
}
}
VBA では下記のようなコードになります。
package = Cells(i, 1).Value
class_name = Cells(i, 2).Value
method_name = Cells(i, 3).Value
return_type = Cells(i, 4).Value
buf = "package " & package & ";" & vbCrLf
buf = buf & vbCrLf
buf = buf & "class " & class_name & " {" & vbCrLf
buf = buf & " public " & return_type & " " & method_name & "() {" & vbCrLf
buf = buf & " //TODO: method implement" & vbCrLf
buf = buf & " ;" & vbCrLf
buf = buf & " ;" & vbCrLf
buf = buf & " ;" & vbCrLf
buf = buf & " }" & vbCrLf
buf = buf & "}"
体験した事のある人もきっと多いでしょうが、正直うんざりします。やってられません。それなので、プログラマの美徳の一つ「怠惰」を発揮して、Ruby でもっと楽にやりましょう。
実は Ruby では、標準添付ライブラリにある ERB を用いることで、同じ結果を下記のコードで得ることができます。
##Excel ファイルを開くあたりは省略しています。
require 'erb'
TEMPLATE = <<EOT
#テンプレート部分 (レイアウト)
package <%= package %>;
class <%= class_name %> {
public <%= return_type %> <%= method_name %>() {
//TODO: method implement
;
;
;
}
}
EOT
#処理部分
package = app.Cells(i, 1).Value
class_name = app.Cells(i, 2).Value
method_name = app.Cells(i, 3).Value
return_type = app.Cells(i, 4).Value
puts ERB.new(TEMPLATE).result
ERB のような機能をテンプレートエンジンといいます。他言語では JSP や Velocity などが有名です。
テンプレートエンジンを用いると、レイアウトと処理とを明快に分離できるので、処理を変えずにレイアウトを自在に変えることができ大変便利です。Web の画面でよく使われる技術ですが、差し込み印刷系の処理や定型文の自動生成などにも力を発揮します。
テンプレートエンジンの種類によっては、特別な環境が必要であったり、専用の制御言語が必要となることもありますが、ERB では、ERB 用のタグを付けて Ruby のコードを入れるだけで使えるため、とても気軽に使う事ができます。
要約すると説明した事柄は以下の通りです。
今回は、Ruby を使って Excel を扱う為の基礎的なテクニックを紹介しました。今回のテクニックで、ちゃっかり手早く Excel を処理するスクリプトを組む喜びを得ることができます。 次回は、じっくり作って長く運用する Excel 利用システムを作りたい場合に活用できるテクニックをご紹介します。
まずは実際に使ってみて、楽しい Ruby を使ったオフィスライフをスタートして下さい。 Enjoy Your Excel’ent Ruby Life!
仕事の企画・設計や工程管理が好物なソフトウェア技術者。
個人的に、ユースケース図と DFD のブームが到来中。
株式会社アイ・プライド チーフシステムエンジニア