「Set Range1 = Range2」と「Range1 = Range2」の違いを検証する(VB/VBAにおけるオブジェクトの代入・比較)

VBAを触り始めて6年目なわけだが、未だにSetの使い方をよく知らなかったので(つまるところオブジェクトというものをちゃんと理解していなかったわけだが)少なくともとSetの使い方をRangeを用いて調べてみた。
今までは何となくRangeオブジェクトを使うときはSetと合わせて使うんだという風に覚えていたわけだが、ググった結果、

「Set Range1 = Range2」とするとオブジェクトとして代入になり、
「Range1 = Range2」とするとRangeのデフォルトプロパティであるValueが代入される

ということになるらしい。

実験準備

早速それを試すため以下のようなコードをVBAで作って検証してみた。

Sub main()
    Dim rng1 As Range, rng2 As Range
    Set rng1 = Range("A1")
    Set rng2 = Range("B1")
    Call MsgBoxRngDetail(rng1)
    Call MsgBoxRngDetail(rng2)
    'rng2 = rng1
    Set rng2 = rng1
    Call MsgBoxRngDetail(rng1)
    Call MsgBoxRngDetail(rng2)
    If rng1 Is rng2 Then
        MsgBox ("rng1 is rng2")
    End If
    If rng1 = rng2 Then
        MsgBox ("rng1 = rng2")
    End If
End Sub

Sub MsgBoxRngDetail(ByRef rng As Range)
    Dim msg As String
    msg = rng.Value
    msg = msg & vbCr & rng.Address
    msg = msg & vbCr & rng.Interior.ColorIndex
    MsgBox (msg)
End Sub

7行目の「rng2 = rng1」と8行目の「Set rng2 = rng1」とのどちらかをコメントアウトし、それぞれの動作を確認した。
Sheet1は以下のように、A1にaが、B1にbが入っている。

実験1:「Set rng2 = rng1」の場合

メッセージボックスは以下のものが順に表示され、シートはこのようになった:

5行目:Call MsgBoxRngDetail(rng1) 6行目:Call MsgBoxRngDetail(rng2)

「Set rng2 = rng1」を実行

9行目:Call MsgBoxRngDetail(rng1) 10行目:Call MsgBoxRngDetail(rng2)

評価

11行目のIf文の条件式がTrueのため 14行目のIf文の条件式もTrueのため
12行目:MsgBox ("rng1 is rng2") 15行目:MsgBox ("rng1 = rng2")

結果:

ということで、「Set rng2 = rng1」ではrng2の中身が丸々rng1と同じになったため、9行目と10行目の表示内容が同じになった。
rng2をrng1で置き換えたようなものだから、シートでは変化は起こらない。

実験2:「rng2 = rng1」の場合

メッセージボックスは以下のものが順に表示され、シートはこのようになった:

5行目:Call MsgBoxRngDetail(rng1) 6行目:Call MsgBoxRngDetail(rng2)

「rng2 = rng1」を実行

9行目:Call MsgBoxRngDetail(rng1) 10行目:Call MsgBoxRngDetail(rng2)

評価

11行目のIf文の条件式がFalseのため 14行目のIf文の条件式もTrueのため
12行目:MsgBox ("rng1 is rng2") 15行目:MsgBox ("rng1 = rng2")

結果:

というわけで、一方で「rng2 = rng1」ではRangeオブジェクトのデフォルトプロパティであるValueの代入が行われただけであり、
つまり「rng2 = rng1」は「rng2.Value = rng1.Value」と等価であることを意味している。
なので、rng2は依然B1セルを指している一方で、B1の値がaに変わっているわけである。
当然「rng1 Is rng2」ではないが「rng1 = rng2」つまり「rng1.Value = rng2.Value」であるから、
評価のメッセージは後半しか表示されないわけだ。

環境:Microsoft Excel 2010/ Microsoft Visual Basic for Applications 7.0