配列を返却する関数についての考察

VBAでは配列を返却する関数を作成することが出来ますが、返却要素が0件を表現するときには少々工夫が必要です。

ここでは、返却要素がないことを通知する、いくつかの方式を考察したいと思います。

方式1:返値の型をVariant型にして、要素が0件のときはNothingを返す

結論から言うと、この方式はうまく機能しません。

なぜなら、Nothingを受け取るときはSetを付ける必要があり、配列が返却された場合は逆にSetを付けるとエラーとなるからです。受け取る側で、予めNothingが返るか、配列が返るか分かりませんので、書きようがないのです。

方式2:方式1と同じだが、返値ではなく引数で受け取る

引数の場合はSetを使わずにNothingを受け取ることが出来ますので、受け取りに関しての問題は解消されます。

ただし、返却された値がNothingかどうかを単純に「Is Nothing」で判断できません。

Nothingが返却された場合はもちろん正しく判定できますが、配列が返却された場合は「オブジェクトが必要です。」というエラーとなってしまうのです。エラーハンドリングで切り分けることは可能ですがあまり綺麗ではないでしょう。

方式3:添え字1以降を有効データとする

ReDim var(0)で必ず配列を初期化して返却するようにします。要素数が0件の場合は、UBound(var)が0となりますので、これにより有効データがあるかないかを判定できるでしょう。

要素数>1 の場合は、var(1) ~ var(UBound(var)) が有効なデータとなります。

有効なデータがある場合だけ処理をし、無効データの有無を特に問わないのであれば、次のようにループ処理できるでしょう。

Dim a() As String = GetArray3() '方式3で返値を返す関数

'有効データは添え字1から開始
'有効データが0件の場合は下記ループは空振りする
Dim i As Integer
For i = 1 To UBound(a)
   '有効データがあればここを通過
Next

方式4:要素数0の場合は初期化されていない配列を返却する

要素数0の場合は、Dim Var() As 型 で宣言された「Var」をそのまま返却します。

この方式の場合、動的配列が初期化済みかどうかを判定する方法がなくてはいけません。

「動的配列が初期化済みかどうかを判定する方法」については、「配列」の項目で説明しています。

 

結論

方式1は論外として、方式2~4は好み次第ということになります。

方式2は返値ではなく引数で受け取るというところがマイナスポイントです。やはり、直感的に理解しやすいほうが好ましいでしょう。あと、Nothingかそうでないかの判定関数はおそらくエラーハンドリングによる切り分けで実装しなければなりません。

方式3は運用次第ですが、自分以外の人がソースを読むことがあり得るならやめたほうが無難でしょう。使う場合はコメントたっぷりにしないと混乱すること必至です。

方式4は動的配列の初期化判定についてはあくまで裏技的方法という感が拭えず、将来的に使えなくなる可能性があるという不安もあります。(現にSgn関数による判定はExcel2017ではエラーとなるようです。)

 

結論として、方式3または方式4ということになります。

どちらも一長一短。難しいですが、個人的には方式4を使っています。

もし、将来的に動的配列の初期化判定が使えなくなれば、その時はその時で関数内のロジックだけ差し替えれば良いだけ、と割り切っています。