和風スパゲティのレシピ

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

変数が配列(Array)かどうか判定する - IsArray関数

変数が配列か調べるには、IsArray関数を使用します。

Sub 変数が配列か調べる()

    ' 純粋に配列で宣言した変数
    Dim 配列変数()
    Debug.Print IsArray(配列変数) ' = True

    ' 全く配列でない変数
    Dim 文字列変数 As String
    Debug.Print IsArray(文字列変数) ' = False

    ' Variantに配列を入れた場合
    Dim Variant変数
    Variant変数 = Array(1, 2, 3) ' = True
    Debug.Print IsArray(Variant変数) ' = True

    ' 配列を返す関数を直接入れた場合
    Debug.Print IsArray(Array(1, 2, 3)) ' = True
    Debug.Print IsArray(Split("1,2,3", ",")) ' = True
    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変数) ' = True!

    ' 配列を返すプロパティを直接入れた場合
    Dim Dictionary変数 As New Dictionary
    Debug.Print IsArray(Dictionary変数.Items) ' = True

End Sub

上記の通り変数に限らず、
関数の返り値や、配列を取得するプロパティもTrue判定してくれます。


ひとつ注意しなければならないのが、
Rangeオブジェクトが.Valueを省略してもTrueとなっている点です。

セル範囲が入っているRangeオブジェクトは、
.Valueをつけると配列、なければRangeオブジェクトを指しますが、
IsArray関数はそもそもRangeオブジェクトでもTrueを返します。

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

 
しかしRangeオブジェクトはもちろん配列ではないため、
例えばUbound(Range変数)は「配列がありません」エラーを返します。


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

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にしたとき」なので、
それもあわせて心の片隅に置いておいてください。