知らずに落ちると抜け出せなくなる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