STEP 3 VBA編

6.配列の受け渡し

配列のデータは、SubプロシージャやFunctionプロシージャの引数、およびFunctionプロシージャの戻り値として、プロシージャ間で相互に受け渡すことができます。ただし、配列の代入と同様、渡す側と受ける側の配列のデータ型は、必ず同じにする必要があります。このことはバリアント型の配列であっても同様ですが、受ける側の引数をバリアント型の変数として指定すれば、渡す側の配列のデータ型に関わらず、受け取ることが可能です(もちろん配列以外も受け取れます)。
なお、プロシージャを記述する際の引数として配列を指定する場合、固定長配列にすることはできません。また、ByVal型の引数も不可で、必ずByRef型(指定を省略した場合はByRef型になります)にする必要があります。Functionプロシージャの戻り値を配列として作成する場合は、データ型を指定する「As Integer」などの末尾に「()」を付けるか、バリアント型にします。
次のコードは、Subプロシージャ「test1」で作成した配列を引数としてFunctionプロシージャ「test2」を呼び出し、その戻り値である配列の2番目の要素を表示します。

Sub test1()
    Dim a(2) As Integer
    a(0) = 1
    a(1) = 3
    a(2) = 5
    MsgBox test2(a())(1)
End Sub

Function test2(b() As Integer) As Integer()
    b(0) = b(0) + 1
    b(1) = b(1) + 2
    b(2) = b(2) + 3
    test2 = b()
End Function

Functionプロシージャ「test2」は次のように書くこともできます。

Function test2(b() As Integer) As Variant
    b(0) = b(0) + 1
    b(1) = b(1) + 2
    b(2) = b(2) + 3
    test2 = b()
End Function

いずれの場合も、「test2(a())」「test2 = b()」の部分で配列変数に付けている空のカッコは、省略も可能です。
Functionプロシージャ「test2」の引数をバリアント型の変数にする場合は、次のような書き方になります。このコードでは、プロシージャ名への代入(戻り値の指定)の際、変数「b」の後にカッコを付けないようにします。

Function test2(b As Variant) As Variant
    b(0) = b(0) + 1
    b(1) = b(1) + 2
    b(2) = b(2) + 3
    test2 = b
End Function

Functionプロシージャをユーザー定義関数として利用することにより、ワークシート上の数式との間で、配列データをやり取りすることも可能です。
戻り値を配列として返すユーザー定義関数で、戻り値のすべてをワークシート上に表示したい場合はセル範囲を選択して、配列数式として確定します。

Function test3(a As Integer) As Variant
    Dim b(1, 1) As Integer
    b(0, 0) = a + 1
    b(0, 1) = a + 2
    b(1, 0) = a + 3
    b(1, 1) = a + 4
    test3 = b()
End Function

一方、ユーザー定義関数の引数として配列を与える場合は、配列定数で指定するか、またはセル範囲に対し演算などの処理を行って配列数式にします。単なるセル範囲は、配列とは見なされません。
配列を受け取るFunctionプロシージャ側では、引数の配列のデータ型は、必ずバリアント型にする必要があります。また、引数を配列ではなくバリアント型の変数にすると、数式で指定された引数がセル範囲の場合にも対応しやすくなります。
引数として配列を受け取る場合、ここで説明したケースと同様、インデックス番号の最小値が「0」ではなく「1」になる点に注意が必要です。たとえば、次のFunctionプロシージャは、引数として与えられた整数の配列にそれぞれ数値を加算し、加算後の最大値を返すものです。

Function test4(a() As Variant) As Integer
    a(0) = a(0) + 1
    a(1) = a(1) + 2
    a(2) = a(2) + 3
    test4 = WorksheetFunction.Max(a())
End Function

このFunctionプロシージャを、ユーザー定義関数として、次のような数式で使用すると、結果は#VALUE!エラーになってしまいます。

=test4({3,5,1})

これは、引数として与えられた配列aのインデックスの最小値が「1」であり、「a(0)」という指定が不適切であるためです。Functionプロシージャ「test4」を次のように修正すれば、同じ数式でもエラーにはなりません。

Function test4(a() As Variant) As Integer
    a(1) = a(1) + 1
    a(2) = a(2) + 2
    a(3) = a(3) + 3
    test4 = WorksheetFunction.Max(a())
End Function

ただし、他のSubプロシージャなどから、引数として3要素の配列を指定してこのFunctionプロシージャを呼び出すと、今度は0が最小値となるため、エラーになってしまいます。VBAの中でも、ユーザー定義関数としても使えるFunctionプロシージャを作成したい場合は、「Option Base 1」を指定するなどして、インデックス番号の最小値を揃えます。

なお、ダウンロード販売している自主制作電子書籍『Excel好きに捧げる 面白・便利な 追加関数50』では、引数や戻り値として配列を扱うユーザー定義関数をいろいろと作成しています(ソースコードの内容については解説していませんが、コード自体は見ることができます)。詳しくはこちらをご覧ください。

<5.ワークシート関数の利用