Ruby: Excelのグラフのデータ領域操作
ExcelのインストールされているWindows環境でExcelを Win32OLE という仕組みで 利用する場合のグラフ操作の方法を説明します。このページを読む前に 「Excel操作(OLE)」 を読んで下さい。
ExcelのVBAで出来る事はほぼRubyからも実行できます。 そこで、「自分でどのようにして、やりたい事をやる方法を見つけ出すか」ですが、 Excelでやりたい事の実例をマクロの記録をONにして実行します。 その結果としてマクロのコードが記録されますので、どのようなコードになったかを確認し、 それを汎用化してRuby流の書き方に変更すればたぶんやりたいことが実現できるでしょう。
グラフを作成するときにはまずExcelで雛型を作成して置き、それを利用してデータの追加や、 グラフ領域の拡大を操作するのが楽です。ここでは、このデータ領域の操作について説明します。
以下ではこのexcel-bookを例題用に使用します。
例題用シート
この例題は Ruby 1.8.7 で確認しています。
Ruby: Exceのグラフ専用シート内のグラフ
グラフはシートの中に置くか、グラフ用の専用のシートとして作成することが出来ます。 それにより、グラフの指定の仕方(存在する場所)が異なります。
まずは、グラフ専用シートに作った場合を説明します。
グラフのデータ領域を変更したときの操作をマクロ記録したものを見てみます。
Sub Macro1()
Sheets("Graph1").Select
ActiveChart.PlotArea.Select
ActiveChart.SetSourceData Source:=Sheets("Sheet1").Range("B2:B16"), PlotBy:=xlColumns
ActiveChart.SeriesCollection(1).XValues = "=Sheet1!R2C1:R16C1"
ActiveChart.SeriesCollection(1).Name = "=Sheet1!R1C2"
End Sub
これを拡張するデータ領域の指定を変数化してRubyで書くとこうなります。
#! ruby -Ks
# -*- mode:ruby; coding:shift_jis -*-
$KCODE='s'
require 'excel'
openExcelWorkbook('g1.xls') do |book|
sheet = book.Worksheets.Item('Sheet1')
sheet.extend Worksheet
chart = book.Charts('Graph1') # シート名でグラフのオブジェクトを取出し
n = 16 ## B2:B16 (16行目までにデータ領域を変更する)
# Rangeオブジェクトで元のデータの範囲を指定する
chart.SetSourceData sheet.Range("Sheet1!$B$2:$B$#{n}")
# X軸データを指定する。
chart.SeriesCollection(1).XValues = sheet.Range("Sheet1!$A$2:$A$#{n}")
# 項目名を指定する
chart.SeriesCollection(1).Name = sheet.Range("Sheet1!$B$1")
book.Save
end
専用のシートとして作られたグラフはbookの下のChartsに含まれます。 シート名をつかってChartsから取出せばオブジェクトとして操作可能となります。
chart.SetSourceDataで元データの範囲をRangeオブジェクトで指定すると範囲が変更できます。
グラフ上の要素項目の数だけSeriesCollection(n)があります。
X軸の値の範囲はXValueで指定して下さい。
項目名はNameで指定して下さい。
これらは指定しなくても正しく表示される事がありますが指定した方が安全です。
データ要素が複数の領域に分かれているときはRangeの指定をカンマで区切って繋げて指定します。
例 : sheet.Range("Sheet1!$C$2:$D$#{n},Sheet1!$G$2:$H$#{n}")
Ruby: Exceのデータシート内のグラフ
データシート内にオブジェクトとして作成したグラフはシートのChartObjectsに含まれます。 ただし、2階層になっていてVBAマクロと同じ指定方法では上手く行きません。
マクロの記録では次のように成ります。
ActiveSheet.ChartObjects("グラフ 2").Activate
ActiveChart.PlotArea.Select
ActiveChart.SetSourceData Source:=Sheets("Sheet1").Range("B2:B15"), PlotBy:=xlColumns
しかし、次のようにアクセスする必要があります。
#! ruby -Ks
# -*- mode:ruby; coding:shift_jis -*-
$KCODE='s'
require 'excel'
openExcelWorkbook('g1.xls') do |book|
sheet = book.Worksheets.Item('Sheet1')
sheet.extend Worksheet
obj = sheet.ChartObjects(1) # シート用のchartオブジェクト
chart = obj.chart # その中にchartが包まれている
chart.SetSourceData sheet.Range("Sheet1!$B$2:$B$#{n}")
chart.SeriesCollection(1).XValues = sheet.Range("Sheet1!$A$2:$A$#{n}")
chart.SeriesCollection(1).Name = sheet.Range("Sheet1!$B$1")
book.Save
end
データシート上のグラフは一段オブジェクトに包まれた形となっています。 取出してしまえば専用シートの例で説明した場合と同じように操作できます。
例題では obj = sheet.ChartObjects(1) とシートを固定の番号で取出しています。 複数のグラフを持ったシートの場合には目的とするグラフを確認して下さい。
グラフにタイトルを付けて、次のようなスクリプトを動かすと確認できます。
#! ruby -Ks
# -*- mode:ruby; coding:shift_jis -*-
$KCODE='s'
require 'excel'
openExcelWorkbook('g1.xls') do |book|
sheet = book.Worksheets.Item('Sheet1')
sheet.extend Worksheet
sheet.ChartObjects.each do |obj|
chart = obj.chart
print "Obj= #{ obj.name }, Chart= #{chart.name}, Title= #{chart.ChartTitle.Characters.Text}\n"
end
end
上記で表示された obj.name の値を使えば obj = sheet.ChartObjects('Chart 2') の様に選択できます。
Excelのマクロの記録でオブジェクトの持つ属性名や手続き名を確認して、使って見ることで 自由に拡張していけると思います。
Excel操作(OLE) ← : Excelグラフ操作 : → 南岳気象データ
お勧めのRuby開発環境
Trail4You 仮想マシンバザール : Ruby統合開発環境仮想マシン上にruby統合開発環境をインストールしてあります。 rvm, git もインストール済みで各種rubyを切替ながら試せます。