「Range("A1") Is Range("A1")はなぜFalseになってしまうのでしょう?」
「RangeオブジェクトはどうしてIs演算子で比較することができないのでしょうか?」
といった趣旨のご質問をいただきました。
Is演算子による比較
例えば、Worksheetオブジェクトの場合は、Is演算子で比較・判定ができます。
以下のマクロを、一番左のワークシートがアクティブな状態で実行するとメッセージボックスにはTrueと表示され、一番左のワークシートがアクティブでなければFalseが表示されます。
Sub アクティブシートが一番左のワークシートかを判定する()
MsgBox _
ActiveSheet Is Worksheets(1)
End Sub
このことを利用して、例えば、一番左のシート以外のシートに処理するといった条件分岐を行うこともできます。
ところがRangeオブジェクトの場合、以下のようなマクロを、A1セルがアクティブなときに実行しても、メッセージボックスにはFalseが表示されます。
Sub アクティブセルがA1セルかはIs演算子では判定できない()
MsgBox _
ActiveCell Is Range("A1")
End Sub
これは何故なのかというのが、ご質問の趣旨です。
RangeオブジェクトがIs演算子で比較できない理由
結論から言うと、Rangeオブジェクトは以下のような動きをするためです。Rangeオブジェクトは取得されるごとに違うメモリアドレスに格納されるため
実際に簡単なマクロを作って確認しましょう。
Worksheetオブジェクトのアドレスを確認するサンプルマクロ
まずは、一番左のワークシートがアクティブな状態で、以下のマクロを実行してみてください。
Dim s1 As Worksheet, s2 As Worksheet, s3 As Worksheet, s4 As Worksheet
Set s1 = Worksheets(1)
Set s2 = Application.Worksheets(1)
Set s3 = ActiveWorkbook.Worksheets(1)
Set s4 = ActiveSheet
MsgBox _
ObjPtr(s1) & vbCrLf & _
ObjPtr(s2) & vbCrLf & _
ObjPtr(s3) & vbCrLf & _
ObjPtr(s4)
メッセージボックスには同じ数字が4つ並ぶはずです。
ObjPtr関数は、オブジェクトのメモリアドレスを返す関数です。
Worksheetオブジェクトを、さまざまな書き方のオブジェクト式でオブジェクト変数に格納して、
Set s1 = Worksheets(1)
Set s2 = Application.Worksheets(1)
Set s3 = ActiveWorkbook.Worksheets(1)
Set s4 = ActiveSheet
それぞれのオブジェクト変数が参照しているメモリアドレスを、ObjPtr関数で取得してメッセージボックスに表示しています。
MsgBox _
ObjPtr(s1) & vbCrLf & _
ObjPtr(s2) & vbCrLf & _
ObjPtr(s3) & vbCrLf & _
ObjPtr(s4)
Worksheetオブジェクトは、どのオブジェクト式、どのプロパティでも、何回取得しても、同じアドレスに格納されるということを表しています。
Rangeオブジェクトのアドレスを確認するサンプルマクロ
次に、A1セルがアクティブな状態で、以下のマクロを実行してみてください。
Dim r1 As Range, r2 As Range, r3 As Range, r4 As Range
Set r1 = Range("A1")
Set r2 = Range("A1")
Set r3 = Cells(1, 1)
Set r4 = ActiveCell
MsgBox _
ObjPtr(r1) & vbCrLf & _
ObjPtr(r2) & vbCrLf & _
ObjPtr(r3) & vbCrLf & _
ObjPtr(r4)
異なる4つの数字がメッセージボックスに表示されます。
Rangeプロパティ・Cellsプロパティ・ActiveCellプロパティと使うプロパティは違っていても、
Set r2 = Range("A1")
Set r3 = Cells(1, 1)
Set r4 = ActiveCell
どれも同じA1セルを返すはずのオブジェクト式です。
特に注目すべきは、
Set r1 = Range("A1")
Set r2 = Range("A1")
の部分です。
r1・r2とも、RangeプロパティでRangeオブジェクトを取得しているにも関わらず、ObjPtr関数は異なる値を返してきます。
つまりRangeオブジェクトは、同じプロシージャの実行中であっても、取得されるごとに別のメモリ領域に格納されるということです。
そしてIs演算子は、メモリアドレスが同じかどうかによって比較を行う演算子なのでしょう。
ですから、
ActiveCell Is Range("A1")
だろうが、
Cells(1, 1) Is Range("A1")
はたまた、
Range("A1") Is Range("A1")
であってもFalseを返し、RangeオブジェクトをIs演算子で比較することができないのでしょう。
Rangeオブジェクトの判定を行うには
このようにRangeオブジェクトの場合はIs演算子で比較・判定を行うことができませんから、例えば、以下のマクロのような判定をする必要があります。
Sub アクティブセルがA1セルかを判定する()
MsgBox _
ActiveCell.Address = Range("A1").Address
End Sub
Home » Excel VBA Rangeオブジェクト » RangeはなぜIs演算子で比較できないのか