MOの気になることを適当に伝えるブログ

moNote

VBA

Rangeブジェクトの認識

投稿日:

いままで結構VBAを書いてきたつもりだが

こんな基本的な? ことも知らなかった orz

通常、オブジェクト変数は 参照型になって Is 演算子 で 比較する。例えば 次のコード

Sub Test1()
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Dim ws3 As Worksheet

    Set ws1 = Worksheets(1)
    Set ws2 = Worksheets(1)
    Set ws3 = ws1
    
    Debug.Print ws1 Is ws2  'True
    Debug.Print ws1 Is ws3  'True
    Debug.Print ws1 = ws2   'エラー
End Sub

ところが ExcelのRangeブジェクト変数は 少し挙動が違う

Sub Test2()
    Dim c1 As Range
    Dim c2 As Range
    Dim c3 As Range

    Set c1 = Range("A1:B2")
    Set c2 = Range("A1:B2")
    Set c3 = c1
    
    Debug.Print c1 Is c2  'False
    Debug.Print c1 Is c3  'True
    Debug.Print c1 = c2   'エラー : 型が一致しません
End Sub

え? って なったのが

Debug.Print c1 Is c2  'False

の 部分。

調べると 「Rangeオブジェクトは取得されるごとに違うメモリアドレスに格納される

??? 確認してみる!

Sub Test3()
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet

    Set ws1 = Worksheets(1)
    Set ws2 = Worksheets(1)
    
    Debug.Print ObjPtr(ws1) = ObjPtr(ws2) 'Treu
End Sub
Sub Test4()
    Dim c1 As Range
    Dim c2 As Range
 
    Set c1 = Range("A1:B2")
    Set c2 = Range("A1:B2")
    
    Debug.Print ObjPtr(c1) = ObjPtr(c2) 'False
End Sub

本当だ。。。。

色々 考察した結果、Rangeオブジェクトって その名の通り「範囲」を指定しているオブジェクトなんだと思います。 セルそのものを示しているのではなく、セルの範囲を指定するためのオブジェクトということです。

Worksheetオブジェクト変数が示す オブジェクトはWorkSheetそのものなので存在すればメモリ上に存在しますが、Rangeオブジェクトが示す オブジェクトはあくまでもセルの範囲なので 取得する毎に 生成され 使わなくなったら破棄される。そして同じセル範囲でも取得時毎に 新しいオブジェクトとして生成される。そう考えると挙動が説明できるように思います。 どうでしょう?
 

エラーコードの質問を受けると こういった気づきもあって 勉強になります。
質問って時に クイズみたいで  なんか 楽しい 。

 

外部リンク

参:RangeオブジェクトはなぜIs演算子で比較できないのか
https://www.relief.jp/docs/excel-vba-is-operator-return-false-range.html

参:オブジェクト変数とは何か
https://excel-ubara.com/excelvba4/EXCEL_VBA_423.html

-VBA
-,

Copyright© moNote , 2020 All Rights Reserved Powered by STINGER.