2016/03/21
参考サイト: Excel VBA 入門講座 オブジェクトとプロパティ、メソッドについて
オブジェクトと、そのプロパティおよびメソッドが主題です。
オブジェクトは、何らかの「もの」のことです。
Excelに即していえば、ワークブック、ワークシート、セルなどがオブジェクトです。
更にいえば、Excelというアプリそのものもオブジェクトです。VBAでは Application という名前で表現されます。
Excelは複数のワークブックを開くことができます。なので、アプリケーションに複数のワークブックオブジェクトをぶら下げることができます。
また、ワークブックには複数のワークシートオブジェクトが含まれるのが一般的です。
このように、オブジェクトを枠組みとして捕らえると、「あれがこれを含む」という階層構造になっています。
プロパティは属性のことです。
Range("A1")
は、A1という番地のセルを示すオブジェクトですが、そのセルに書き込まれている値を示すValueはプロパティの一種です。
Worksheets(1)
は、第1ワークシート(オブジェクト)を指しますが、これにはNameというプロパティがあります。ワークシート名を示します。
プロパティには一般に文字や数値が代入されています。
第1ワークシートには通常、Sheet1 という名前がついているので、Worksheets(1).Name
には "Sheet1"
という文字列が代入されています。
そして、第1ワークシートオブジェクトを指し示すのに Worksheets("Sheet1")
という書き方もできます。
プロパティに、新たに文字や数値を代入することもできます。たとえば下のとおり。
Range("A1").Value = "test"
Worksheets(1).Name = "第1の集計表"
メソッドは、オブジェクトに対して何らかの処理を施すものです。
Range("A1").Clear
とすれば、A1セルに書き込まれている内容が消去されます。
Clearが「消去する」という処理を施すためのメソッドです。
セルオブジェクトのValueプロパティは、セルに書き込まれているデータを取り出したりセットしたりするのに用います。
その使用例を3種類のスクリプトで示します。
参考サイトに掲載されているマクロをBook1.xlsというワークブックに登録するためのrubyスクリプトを掲げます。セルオブジェクトのValueプロパティを使う例です。
1# encoding: Windows-31J 2require "./exlap" 3 4macro_str = <<'EOS' 5Sub SetValue() 6 Worksheets("Sheet1").Range("A1").Value = "HELLO EXCEL VBA WORLD" 7End Sub 8EOS 9 10macro_name = "SetValue" 11File.delete("Book1.xls") if test(?e, "Book1.xls") # 既存のBook1.xlsを削除 12Exlap.new("Book1.xls") do |wb| 13 wb.macro_add(macro_str) 14 wb.Application.MacroOptions("Macro"=>macro_name, "ShortcutKey"=>"j") 15 wb.save 16end
上のスクリプトが test.rb という名前のファイルとして保存されている場合、次のようにすれば実行できます。
ruby.exe test.rb [enter]
上のrubyスクリプトの実行に成功すれば、Book1.xlsというファイルができます。
Book1.xlsをExcelで開いてから Control + j
を入力すれば組み込んだマクロが実行されます。結果、A1セルに HELLO EXCEL VBA WORLD
が書き込まれます。
スクリプト中、macro_str = <<'EOS
と書かれた行と EOS
とだけ書かれた行の間にあるのがVBAのマクロです。
このサンプルの肝は下の1行です。
Worksheets("Sheet1").Range("A1").Value = "HELLO EXCEL VBA WORLD"
ワークシートオブジェクトの下にあるセルオブジェクトについて、Valueプロパティをセットしています。
アプリケーションやワークブックの記述は見当たりませんが、VBAでは、暗黙のうちに選択されているものを省略できるので、「わざわざ書かなくても大丈夫」ということです。
しかし、rubyで同じことをやろうとした場合は省略できません。
ちなみに、省略しないでマクロを書くと、たとえば下のようになります。
Application.Workbooks(1).Worksheets("Sheet1").Range("A1").Value = _
"HELLO EXCEL VBA WORLD"
長いので2行にしましたが、1行にしておいてもかまいません。
1行目の行末の '_'
は、「改行はしてあるけどつぎの行に続くよ」ということを示す記号です。
今度は同じことをrubyスクリプトで行います。exlapは用いません。
ワークブックにマクロを組み込む方式ではなく、WindowsのOLEという仕組みを利用してExcelを外部から操作します。
飛行機の操縦に例えると、パイロットを乗せて操縦するのがマクロの組み込み、管制塔からラジコン操作のように飛行機を動かすのがOLEです。
rubyにはOLEを利用するためのライブラリ(win32ole)が標準で用意されています。それを用います。
スクリプトは下のとおり。
1# encoding: Windows-31J 2require "win32ole" 3 4def fullpath(filename) 5 fso = WIN32OLE.new("Scripting.FileSystemObject") 6 return fso.GetAbsolutePathName(filename) 7end 8 9File.delete("Book1.xls") if test(?e, "Book1.xls") # 既存のBook1.xlsを削除 10app = WIN32OLE.new("Excel.Application") 11wb = app.Workbooks.Add() 12ws = wb.Worksheets("Sheet1") 13ws.Range("A1").Value = "HELLO EXCEL VBA WORLD" 14wb.SaveAs(fullpath("Book1"), -4143) 15app.Quit
上のスクリプトにより作成される Book1.xls をExcelで開くと、A1セルに HELLO EXCEL VBA WORLD
が書き込まれているはずです。
本項のテーマであるオブジェクトについてみると、アプリケーションオブジェクトを変数appに、ワークブックをwbに、ワークシートをwsに代入しています。
VBAのマクロのように、アプリケーションやワークブックに関する記述を省略することはできません。
とはいえ、VBAのマクロ記述と同じ部分が少なくないのも分かっていただけると思います。アルファベットの大文字で始まる名前は、ほとんどがVBAのマクロ記述そのままだと思ってもらっていいはずです。
あと、全自動の一括処理であるため、ワークブックを保存し、Excelアプリケーションの終了処理も行っています。
保存しなければセルへの書き込みという処理の痕跡が残らないし、Excelが終了せずにWindowsのタスクに残ったままだと気分がよくありません。
SaveAsというのはワークブックのメソッドで、「名前を付けて保存」に相当します。
その第1パラメータはファイル名(ワークブックの名前)ですが、それを単2 “Book1” とすると、ユーザーのドキュメントフォルダ(以前の言い方だとマイドキュメント)に保存されます。カレントフォルダには保存されません。そのため fullpath() を適用しています。
SaveAsの第2パラメータはワークブックの種類です。Excel2003の形式(xls)、Excel2007以降の形式(xlsx)、マクロ有効の形式(xlsm)などのどれにするかを指定します。整数値で指定します。
-4143は、Excel2003形式を指定する値です。xlsx形式にしたい時は 51 に、xlsm形式なら 52 にします。
exlapを用いて同じ処理のスクリプトを書くと、下のようになります。
オブジェクトの扱いはwin32oleの場合と同様です。
exlapでは、ワークブックを開くに当たってその名前を指定します。既に存在しているワークブックであれ、まだ存在していないものであれ(つまり新規であれ)、ともかく名前を指定します。
そうすることにより、ワークブックを保存する時に改めて名前を指定しなくてもよくなります。wb.save
だけでいいことになります。
win32oleの時の fullpath()
が出てきませんが、exlapでは内部において暗黙のうちに fullpath()
と同じ処理が適用されます。
ワークブックの形式(xls, xlsx, xlsmなど)は、ワークブックの名前の拡張子から自動的に判別されます。
wb.ss("Sheet1")
の ss()
は、select_sheet()
の省略名です。VBAの Worksheets()
と同じように使えます。
exlapでは、rubyの「ブロック」という機構を利用して、もう少し簡潔なスクリプトにすることができます。それを掲げます。
複数行にわたる「do …… end」の部分が「ブロック」です。
最後の行の end で「ブロック」が終了するわけですが、その時点でExcelアプリケーションの終了処理が自動的に呼び出されます。
セルオブジェクトのSelectメソッドは、該当のセルを注目セルにする(選択する)ためのメソッドです。Selectされたセルにカーソルが移動します。
参考サイトに掲載されているマクロをBook1.xlsというワークブックに登録するためのrubyスクリプトを掲げます。セルオブジェクトにSelectメソッドを適用する例です。
作成されるBook1.xlsをExcelで開いてから、Control + j
をキーボードで入力すると、登録したマクロが実行されます。カーソルがA1のところに移動するはずです。
1# encoding: Windows-31J 2require "./exlap" 3 4macro_str = <<'EOS' 5Sub SelectCell() 6 Worksheets("Sheet1").Range("A1").Select 7End Sub 8EOS 9 10macro_name = "SelectCell" 11File.delete("Book1.xls") if test(?e, "Book1.xls") # 既存のBook1.xlsを削除 12Exlap.new("Book1.xls") do |wb| 13 wb.macro_add(macro_str) 14 wb.Application.MacroOptions("Macro"=>macro_name, "ShortcutKey"=>"j") 15 wb.save 16end
Selectが Range("A1")
というセルオブジェクトに適用されています。
Selectは、文字通り「選択する」という処理を施すメソッドです。カーソルがB1やC1にあっても、このマクロを実行するとカーソルがA1に移動します。A1が選択される訳です。
同様の処理をwin32oleのrubyスクリプトで書いてみようと思いますが、Selectメソッドでカーソルを移動させるだけだと、全自動一括処理では「実行された」という実感が得られません。
そこで、ちょっと はみ出しぎみですが、A1, B1, C1 の三つのセルに文字を書き込んだあと、B1のセルの内容をClearメソッドで消去する処理をやってみます。Selectも使います。
1# encoding: Windows-31J 2require "win32ole" 3 4def fullpath(filename) 5 fso = WIN32OLE.new("Scripting.FileSystemObject") 6 return fso.GetAbsolutePathName(filename) 7end 8 9File.delete("Book1.xls") if test(?e, "Book1.xls") # 既存のBook1.xlsを削除 10app = WIN32OLE.new("Excel.Application") 11wb = app.Workbooks.Add() 12ws = wb.Worksheets("Sheet1") 13ws.Range("A1:C1").Value = "cat", "dog", "fox" 14ws.Range("B1").Clear 15ws.Range("B1").Select 16wb.SaveAs(fullpath("Book1"), -4143) 17app.Quit
ws.Range("B1").Select
として、B1セルにSelectメソッドを適用していますが、「そんなことして意味があるのだろうか」と疑問に思われるかもしれません。でも、意味はあります。
ワークブックを保存する直前にB1セルにカーソルを移動すると、あとからワークブックを再度オープンした時に、カーソルがA1ではなくB1にきます。Selectしたことが反映されたことになります。
先のwin32oleのスクリプトと同じ内容のものをexlap利用の形式で掲げます。
上のスクリプトについて、特に補足する必要はないと思います。