【Excel VBA入門 第15回】配列をFunction・Subに渡す・受け取る方法

スポンサーリンク
Excel VBA

イントロダクション

前回(第14回)では、引数を省略可能にする Optional の使い方を学んだ。

今回は、複数のデータをまとめて扱える「配列」を、FunctionSub の引数として受け渡す方法を解説しよう。1件ずつ引数を渡すのではなく、まとめて処理できるようになると、コードの幅がぐっと広がる。

配列の基本をおさらい

配列とは、複数の値を1つの変数名でまとめて管理できる仕組みである。
なお、コードは、第12回で作成した Module1 に引き続き追記していく。

Sub 配列の基本()
    Dim 得点(2) As Long   ' 要素数3の配列(添字0~2)
    得点(0) = 80
    得点(1) = 65
    得点(2) = 92

    Debug.Print 得点(1)   ' → 65
End Sub

配列をプロシージャに渡す

配列を引数として渡す場合は、引数名の後ろに () を付けて宣言する。

Sub 配列を表示する(ByRef 対象配列() As Long)
    Dim i As Long
    For i = LBound(対象配列) To UBound(対象配列)
        Debug.Print 対象配列(i)
    Next i
End Sub
Sub 配列表示の呼び出し例()
    Dim 得点(2) As Long
    得点(0) = 80: 得点(1) = 65: 得点(2) = 92

    配列を表示する 得点
End Sub

配列全体はByRefで渡す

前回・前々回で ByVal(値渡し)と ByRef(参照渡し)の違いを学んだが、VBAでは、DimReDimStatic などで宣言した配列全体は、ByVal では渡せず、ByRef で渡す必要があるという特徴がある。配列全体をコピーするのは処理負荷が大きいため、常に参照渡しになる仕組みだと理解しておこう。

そのため、配列を引数に取るプロシージャの中でうっかり配列の中身を書き換えると、呼び出し元の配列にも影響が及ぶ。意図しない変更を避けたい場合は、プロシージャ内で配列の値を書き換えないよう注意するか、必要であれば配列をコピーしてから処理するとよい。

LBoundとUBoundで配列の範囲を安全に扱う

配列を扱う関数を作る際、添字の範囲を決め打ちで 0 To 2 のように書いてしまうと、配列のサイズが変わった時に対応できなくなる。

  • LBound(配列):配列の最小添字を取得
  • UBound(配列):配列の最大添字を取得

この2つを使うことで、配列のサイズに依存しない汎用的なコードが書ける。

実践!配列の合計・平均を計算するFunction

配列を受け取り、合計と平均を返すFunctionを作ってみよう。

Function 配列の合計(対象配列() As Long) As Long
    Dim i As Long
    Dim 合計値 As Long

    For i = LBound(対象配列) To UBound(対象配列)
        合計値 = 合計値 + 対象配列(i)
    Next i

    配列の合計 = 合計値
End Function

Function 配列の平均(対象配列() As Long) As Double
    配列の平均 = 配列の合計(対象配列) / (UBound(対象配列) - LBound(対象配列) + 1)
End Function
Sub 配列集計を実行する()
    Dim 得点(2) As Long
    得点(0) = 80: 得点(1) = 65: 得点(2) = 92

    Debug.Print "合計: " & 配列の合計(得点)
    Debug.Print "平均: " & 配列の平均(得点)
End Sub

このように、一度作ったFunctionを組み合わせて別のFunctionから呼び出すこともできる。処理を細かく部品化しておくメリットが実感できるはずだ。

セル範囲を配列として一括取得する

実務でよく使うテクニックとして、セル範囲の値を一括で配列に読み込む方法も紹介しておこう。

Sub セル範囲を配列に取り込む()
    Dim データ As Variant
    データ = Range("A1:A10").Value   ' 2次元配列として一括取得

    Debug.Print データ(1, 1)   ' 1行1列目の値
End Sub

セルを1つずつループで読み込むよりも、Range.Value で一括取得した方が処理速度は格段に速い。大量データを扱う際はぜひ活用したい手法である。

まとめ

今回は、配列をFunction・Subの引数として受け渡す方法を学んだ。

  • 配列を引数に取る場合は 対象配列() As 型 のように () を付けて宣言する
  • 配列は常に参照渡し(ByRef相当)で扱われる
  • LBound / UBound を使うと配列サイズに依存しない汎用的なコードが書ける
  • セル範囲は Range.Value で一括して配列に取り込むと高速に処理できる

配列を自在に扱えるようになると、集計処理やデータ検証など、実務で役立つマクロの幅が大きく広がる。

次回(第16回)は、これまで作ってきたFunction・Subを実務でも安心して使えるようにするための「エラー処理」の基本を解説していこう。

コメント

タイトルとURLをコピーしました