はじめに
ExcelVBAでは、アクティブシートのセルの値を編集する時、ワークシートの指定を省略することができるが、アクティブでないシートのセルの値が欲しい場合は、ワークシートを指定する必要がある。
ワークシートを指定するには、Worksheetsオブジェクトを使う。※1 Worksheetsオブジェクトは現在のブックが持つシート配列を扱うオブジェクトだ。このようなオブジェクトの配列の事をVBAでは「コレクション」という言い方をする。
(※1 Worksheetsオブジェクトの他に Sheetsオブジェクトというのもあるが、こちらはワークシートだけでなくグラフ表示用のシートなども扱うオブジェクトになる。)
Worksheetsオブジェクト
ワークシートを指定する方法は2つある。1つは数値で指定する方法。もう1つはシート名で指定する方法だ。
ワークシートを数値で指定する
数値でワークシートを指定するには以下のように記述する。
Worksheets(1)
Worksheetsの持つワークシート配列は 1 から始まる点に注意しよう。(通常の配列は 0 から始まる事もあるのだ。) 一方、最後のワークシートに関しては、ワークシートが増減するので、Countというプロパティを使う。
Countプロパティは、ブックの持つワークシートの数を保持している。ワークシートの数を表示するプログラムは以下のようになる。
Sub testWorksheets()
Debug.Print Worksheets.Count
End Sub
ワークシートをシート名で指定する
シート名でワークシートを指定するには以下のように記述する。
Worksheets("Sheet1")
シート名は文字列で指定するので、シート名に “” を付ける。もちろん文字列型の変数を指定しても良い。
全てのシート名を表示するプログラム
ブックにある全てのワークシートを巡回してシート名を表示するプログラムは以下のようになる。
Sub testWorksheets2()
Dim i As Long
For i = 1 To Worksheets.Count
Debug.Print Worksheets(i).Name
Next i
End Sub
このプログラムでは、For文を使ってWorksheetsオブジェクトにある(単体シートの)Worksheet オブジェクトを巡回している。
Worksheets オブジェクトは配列(コレクション)であるのに対して、Worksheet オブジェクトはワークシート単体のオブジェクトで扱いは異なるので注意しよう。
実行するとブックにあるシート名が表示される。
例として以下のようなシート構成でプログラムを実行してみる。


【結果】
A
B
C
D
ここから A シートを最後尾に移動して実行してみると以下のようになる。


【結果】
B
C
D
A
プログラムの結果は、表示されたExcelシートの順番になるが、プロジェクトウインドウに変化はない。
次は、B シートを非表示にして実行してみる。


【結果】
B
C
D
A
結果は前回と同じで、非表示のシートもシート名を得る事ができる。(セルの値も取得・設定可能だ。)
但し、非表示のシートを Select(選択)する事はできない。
Sub testworksheets3()
Debug.Print Worksheets("B").Select
End Sub
B シートを非表示で上記のプログラムを実行すると以下のようなエラーメッセージが表示される。

これらの挙動を理解しておくと、エラーの原因に気付く事ができるだろう。
For Each In
繰り返し処理の特別バージョンを紹介しよう。For Each sh In は、コレクションでよく使用される。
「コレクション」とは、オブジェクトの配列の事を言う。
構文は以下のような感じだ。
For Each コレクション要素 In コレクションや配列
内部処理
Next コレクション要素
Sub testworksheets3()
Dim sh
For Each sh In Worksheets
Debug.Print sh.Name
Next sh
End Sub
使い方は、まず繰り返しを行う単体のコレクション要素を変数として宣言する。コレクション要素の変数はバリアント型がよく使われるが、Object型や固有のオブジェクト型でも可能だ。
For Each に続き、コレクション要素の変数を記述したら、In の後にコレクションを記述する。
コレクションは、Worksheets と s が付いた複数形になっている所に注目しよう。
見てわかる通り、1,2,3,,,という風に順番で繰り返すというよりは、コレクション(配列)の要素に対して1つずつ繰り返し処理を行うというイメージだ。なので逆順に繰り返すような細かい処理には向いていない。
初心者の方には、通常のFor文をマスターして、余裕がある人は特別バージョンとして覚えて貰えれば良いと思う。サンプルコードを参考にしたい時によく出てくるので紹介した次第だ。
各シートのデータの参照
普段のExcelシートの操作では、目的のワークシートを選択してから値を参照する。この方法は、「マクロの記録」などで良く使用される方法だ。そもそも「マクロの記録」はユーザーの行った操作を記録するのだから Select してから、Selection に対して何かを行うという形が多い。
Sub Macro1()
'
' Macro1 Macro
'
'
Range("B2").Select
Selection.Copy
Sheets("Sheet2").Select
Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End Sub
これは、アクティブシートのB2セルをコピーして、Sheet2のA1に値のみの貼り付けを行った例になる。
「マクロの記録」では、Select して、Selection に対して Copy 。次にシートを変えるために Sheet2 を Select して、A1セルを Select 。最後に、Selectionに対して、PasteSpecial で貼り付けを行っている。
これをこれまで学んだ書き方で表現すると以下のようになる。
Sub myMacro2()
Worksheets("Sheet2").Range("A1") = Range("B2")
End Sub
簡単に書けたのは、Select や Selection を使わない事。さらに、値のコピーなので、プロパティ値の代入で済ませているからだ。
また、Macro1では、現在のシートが Sheet2 に変更されるが、myMacro2 では、現在のシートは変化しない。
つまり、どのシートの値を取得・設定するにしても、そのシートを Select する必要はないのだ。
このようにVBAでは、シートやセルを Select するということは稀で、使用する場合はユーザーに対して明示的に選択している事を示したい場合にのみ使用することになる。
尚、Macro2 では現在のシートが変化すると結果が異なってしまう。コピー元もシートを固定すればユーザーがどのシートを開いていても結果は同じになる。
Sub myMacro3()
Worksheets("Sheet2").Range("A1") = Worksheets("Sheet1").Range("B2")
End Sub
まとめ
VBAでセルを指定する場合、シートを跨ぐようなコピーを行う場合、シート指定は、Worksheetsコレクションに対して、数値で指定する場合とシート名で指定する場合がある。
Worksheets(1)
Worksheets(“Sheet1”)
ブック内のワークシートの数は、Countプロパティで取得できる。
Worksheets(“Sheet1”).Count
シート名のプロパティは Name を使う。
Worksheets(1).Name
ブック内のシートは、For文をつかって巡回できる。For Each sh In に関しては余裕のある人は覚えておこう。
また、シートを指定してセルの値をコピー・貼り付けを行う場合、現在のシート(アクティブシート)は変化することはないので覚えておこう。
コメント