和風スパゲティのレシピ

日本語でコーディングするExcelVBA

IsArray(Range)は.Valueを省略してもTrue

知らずに落ちると抜け出せなくなるVBAの落とし穴です。

  • IsArrayで判定したはずの変数が配列ではない
  • IsArrayがTrueなのにUbound/Lboundがエラーになる

あたりにお悩みの方は、この落とし穴に落ちていないかご確認ください。

IsArray関数にRangeオブジェクトを渡したときの仕様

IsArray関数は変数などが配列かを調べる関数ですが、
Rangeオブジェクトに対してもTrueを返すという性質があります。

' 直接Rangeを渡した場合
Debug.Print IsArray(Range("A1:C3").Value) ' これはもちろんTrue
Debug.Print IsArray(Range("A1:C3")) ' なんとこっちもTrue

' Range変数を入れた場合
Dim Range変数 As Range
Set Range変数 = Range("A1:C3")
Debug.Print IsArray(Range変数) ' 純粋なRange変数もTrue

' Range変数(単独セル)を入れた場合
Set Range変数 = Range("A1")
Debug.Print IsArray(Range変数) ' この時はさすがにFalse

上記の通り、セル範囲が入ったRangeオブジェクトがTrueになってるのがわかります。


セル範囲が入っているRangeオブジェクトは、

  • .Valueをつけると配列
  • .ValueがなければRangeオブジェクト

を返す仕様のオブジェクトですが、
いずれにせよIsArrayはTrueになりますのでご注意ください。


この仕様で発生するもっともありがちな事故として、

Sub エラーテスト()
    Call 配列の要素すべてをループする(Range("A1:C3")) ' ← .Valueを書き忘れた
End Sub

Sub 配列の要素すべてをループする(Arr)
    
    If IsArray(Arr) = False Then Exit Sub ' .Valueの書き忘れを検知できない
    
    Dim i As Long
    For i = LBound(Arr) To UBound(Arr) ' ← ここでエラー
        ' 配列の要素ごとの処理
    Next
    
End Sub

こんな風に.Valueを書き忘れたとしてもIsArrayを突破してしまいます。

この仕様には注意しておきましょう。


とはいえ、普通に変数に代入する

Dim Arr
Arr = Range("A1:C3")

この文であれば、.Valueがなくても普通に配列が入ります。
※ 間違ってSetを書いてしまうようなことがなければ


この事故が発生するのは主に「関数の引数をVariantにしたとき」なので、
それもあわせて心の片隅に置いておいてください。


IsArray関数の詳しい仕様についてはこちらをどうぞ
www.limecode.jp