Home » ExcelVBA Rangeオブジェクト » RangeはなぜIs演算子で比較できないのか

RangeはなぜIs演算子で比較できないのか

対象:Excel2007, Excel2010, Excel2013

「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オブジェクトがIs演算子で比較できない理由
Rangeオブジェクトは取得されるごとに違うメモリアドレスに格納されるため

実際に簡単なマクロを作って確認しましょう。

Worksheetオブジェクトのアドレスを確認するサンプルマクロ

まずは、一番左のワークシートがアクティブな状態で、以下のマクロを実行してみてください。

Sub 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)

End Sub

メッセージボックスには同じ数字が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セルがアクティブな状態で、以下のマクロを実行してみてください。

Sub Rangeオブジェクトのアドレスを確認する()

 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)

End Sub

異なる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 » ExcelVBA Rangeオブジェクト » RangeはなぜIs演算子で比較できないのか

「ExcelVBA Rangeオブジェクト」の記事一覧

検索


Copyright © インストラクターのネタ帳 All Rights Reserved.

.