配列の初期化のチェック
VBAで動的配列を使う際に、その動的配列がちゃんと動的配列として初期化されているのかをチェックしたい場合があります。
多いのは関数の引数に動的配列を用いた場合でしょうね。
関数を呼び出す側がちゃんと動的配列を初期化していない場合に、関数側で異常終了しないように対応しておく場合などですね。
もし配列の初期化がされていない状態でUBound関数を使うと、「実行時エラー’9′ インデックスが有効範囲にありません」とエラーダイアログが表示されます。
確実に初期化されていることが分かっているのであればチェックは不要と判断することもあると思いますが、初期化されているのか分からない場合や、引数に配列を持つ関数の場合はチェック処理は入れておいた方が無難です。
配列の初期化チェック方法
初期化の判定方法にはいくつかありますが、私はSgn関数を利用することをお勧めします。
理由はこれが一番単純だからです。
Sgn関数は引数の数値が、正、負、0、のいずれであるかを調べる関数ですが、初期化されていない動的配列を渡すと0を返す特性があります。
これを利用します。
ソースコード
以下の関数で配列の初期化状態を判定します。
引数に配列を渡して、それが初期化されているかを関数戻り値で返します。
1 2 3 4 5 6 7 8 9 10 |
'// 配列初期化判定関数 '// 引数 :(IN) 配列変数 '// 戻り値 :Boolean 初期化済み=True、未初期化=False Function IsInitArray(ary()) As Boolean If Sgn(ary) <> 0 Then IsInitArray = True Else IsInitArray = False End If End Function |
以下は上記の配列初期化判定関数を使った例です。
8行目では初期化された配列を渡し、12行目では初期化されていない配列を渡しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
'// テスト関数 Sub IsInitArrayTest() ReDim a(0) Dim b() Dim ret '// 初期化済みの配列をチェック ret = IsInitArray(a) Debug.Print ret '// Trueが出力される '// 未初期化の配列をチェック ret = IsInitArray(b) Debug.Print ret '// Falseが出力される End Sub |
ソースの説明
IsInitArray関数に引数で配列を渡すとSgn関数を介してTrueかFalseを返します。
Trueは初期化済み、Falseは未初期化です。
単純な関数ですね。
テスト関数のIsInitArrayTestでは、Redimと(0)で初期化済みの変数aと、Dimと()で未初期化の変数bをそれぞれIsInitArray関数で判定しています。
配列の初期化の判定にSgn関数を使う理由
UBoundのエラーをOn Error Gotoでキャッチしてエラー判定処理を行う方法もあることはあるのですが、私はおすすめしません。
Sgn関数がどういう実装をしているのかはわかりませんが、おそらく内部ではUBound関数+On Error Gotoのような概念での処理が実装されているのではないかと思います。
ライブラリ化されているためVBAで実装するよりも高速なはずです。
それを考えると、わざわざVBAでエラーをキャッチするような実装をする必要性を感じません。
また、Sgn関数は正負を返す関数ですが、数値が0より大きいか小さいかを判定するためにSgn関数を用いることはほとんどないと思います。
普通は以下のように書きます。
Sgn関数を使うより高速でしょうし、それに数値比較というごく一般的なコードのため分かりやすいです。
1 2 3 4 5 6 7 8 9 10 |
'// 0より大きい場合(正) If a > 0 Then '// 省略 '// 0より小さい場合(負) ElseIf a < 0 Then '// 省略 '// 0の場合 Else '// 省略 End If |
であれば、一体Sgn関数の意義はなんなのでしょうか。
自分には思いつきません。
なので、用途がない(言い過ぎ?)Sgn関数に用途を見出して便利に使いましょう。