マクロを動作させるのに、数値や文字列を変数に代入することは日常茶飯事です。
しかし実は、ワークシートやセルなどのオブジェクトも変数に代入することができます。
ワークシートを変数に代入するためには、数値や文字列、論理値( True / False )の代入とは少し違った面があります。
それは、Dimステートメントで変数を宣言した後、実際の代入にSetステートメントを使うことです。
Sub test16() Dim R As Integer Dim C As Integer For R = 1 To 5 For C = 1 To 5 Cells(R+5, C+1) = Worksheets("元").Cells(R, C) ←@ Next C Next R End Sub |
これは、オブジェクト変数を使っていないプロシージャです。 @ ここでは、「元」というワークシートのデータを 今現在アクティブになっているワークシートに 下に5行右に1列ずらして書き込んでます。 |
Sub test17() Dim 元 As Worksheet ←A Dim R As Integer Dim C As Integer Set 元 = Worksheets("元") ←B For R = 1 To 5 For C = 1 To 5 Cells(R + 5, C + 1) = 元.Cells(R, C) ←C Next C Next R End Sub |
オブジェクト変数を使うと、このようになります。 A ここで、ワークシートを代入できるよう宣言します。 B ここで、「元」という変数に、ワークシートを代入します。 C 記述するときは、オブジェクトとして使います。 日本語表記もしてあるので、すっきりとして見やすいです。 |
Sub test18() Dim 名前 As String ←D Dim R As Integer Dim C As Integer 名前 = "元" ←E For R = 1 To 5 For C = 1 To 5 Cells(R + 5, C + 1) = Worksheets(名前).Cells(R, C) ←F Next C Next R End Sub |
ちなみに、文字列を使った場合は、こんなふうになります。 D 文字列として宣言します。 E 「元」という文字を、変数に代入します。 F ワークシートを扱うときには、ワークシート名として書きます。 オブジェクト変数を使った方が、見栄えがよくなります。 |
オブジェクト変数を使うと、次のようなこともできます。
下のプロシージャは、アクティブになっているブックの全部のワークシート名を表示します。
これを応用すると、条件を満たすワークシートだけ処理したり、ワークシートの削除をしたりができます。
Sub test19() Dim Ws As Worksheet For Each Ws In Worksheets ←@ MsgBox Ws.Name ←A Next Ws End Sub |
@ アクティブなっているブックの中から、 1つ1つワークシートを呼び出します。 呼び出したときに、Wsというオブジェクト変数に代入します。 A 呼び出したワークシートの名前を表示します。 |
オブジェクト変数では、当然、セルも扱うことができます。
下のプロシージャでは、数値を偶数と奇数に分類しています。
Sub test20() Dim Rg As Range ←@ Dim R As Integer For R = 2 To 11 If Cells(R, 4) Mod 2 = 0 Then ←A Set Rg = Cells(R, 1) ←B Else Set Rg = Cells(R, 2) ←C End If Rg.Value = Cells(R, 4) ←D Next R End Sub |
@ ここで、セルを代入できるよう宣言します。 A 4列目の数値を2で割った余りで、 処理を分岐します。 B 偶数の時は、1列目を代入します。 C 奇数の時は、2列目を代入します。 D セルの値に、4列目の値を代入します。 |
Sub test21() Dim R As Integer For R = 2 To 11 If Cells(R, 4) Mod 2 = 0 Then Cells(R, 1) = Cells(R, 4) Else Cells(R, 2) = Cells(R, 4) End If Next R End Sub |
実際に、このようなプロシージャが必要になったときは、 左のように組む方が多いかもしれません。 ただ、読み込む位置を変更したりするとき、 (例えば、元データが5列目になった場合) このプロシージャだと3カ所修正しなければなりませんが、 上のプロシージャだと2カ所で済みます。 行数の多いプロシージャになったとき、 その差はもっと大きなものになるので、 まとめることができるなら、 まとめた方がメンテナンスは楽になります。 |
セルの扱いをもっと広げて、範囲として扱うこともできます。
次のプロシージャは、ある範囲の中でセルを選択し、アドレスを表示します。
Sub test22() Dim 範囲 As Range Dim Rg As Range Set 範囲 = Range("B3:D6") ←@ For Each Rg In 範囲 Rg.Select ←A MsgBox Rg.Address(ReferenceStyle:=xlR1C1) 'R1C1形式で ←B Next Rg End Sub |
@ 扱う範囲を設定します。 プロシージャ内では、RangeとCellsを混在して使えるので、 そのときの使い勝手がよい方を使うと便利です。 A ここで、セルを選択しています。 B ここでは、R1C1形式でアドレスを表示しています。 A1形式で表示したければ、Rg.Address だけにします。 |
Sub test23() Dim R As Integer Dim C As Integer For R = 3 To 6 ←C For C = 2 To 4 ←D Cells(R, C).Select MsgBox Cells(R, C).Address(ReferenceStyle:=xlR1C1) 'R1C1形式で Next C Next R End Sub |
ちなみに、範囲を使わないで書くと、こんな感じです。 ここで考えなければいけないのは、範囲が変更になったときです。 上のプロシージャであれば、@の内容を書き換えれば済みます。 ところが、このプロシージャだと、CとDを書き換えなければなりません。 このプロシージャはまだ処理が簡単ですが、複雑なものになると、 修正する箇所も莫大に増えてきます。 そうなると、メンテナンスにも非常に時間がかかります。 上のプロシージャで、行位置を知りたいときは、Rg.Rowで求められますし、 列位置を知りたければ、Rg.Columnで求められるので、不都合もありません。 |
オブジェクト変数が空であることを調べる時は、「Is Nothing」を使います。
したがって、Aというオブジェクト変数を調べる場合なら、
If A Is Nothing Then Msgbox "空です。"
と、こんな感じになります。
反対に空でないことを調べる場合は、
If Not A Is Nothing Then Msgbox "空ではありません。"
となります。
データ型 | 空のとき | 備考 | (例) 空のとき | (例) 空でないとき |
オブジェクト型 Range,Worksheet |
Nothing | ないという意味。 (空にするときは、Set A = Nothing ) |
If A Is Nothing Then 〜 | If Not A Is Nothing Then 〜 |
数値型 Integer,Singleなど |
0 | 1つもないので0。(数値としては存在します。) (0にするときは、A = 0 ) |
If A = 0 Then 〜 | If A <> 0 Then 〜 |
文字列型 String |
"" | 長さが0の文字列が入っているという扱い。 (無しにするときは、A = "" ) |
If A = "" Then 〜 | If A <> "" Then 〜 |