VBA 参照不可変数を作成するTake2 for Run関数
2020年7月13日 参照不可変数の使い方研究その2です。こんどは真髄さんの記事を参考にrun関数で参照不可変数がRun関数でどのように機能するのか検証していきます。


検証コード(わかりやすくするために分割しています)
Option Explicit

Sub main()
    '@topic     参照不可を利用した組み込み関数の呼出し
    '@-----------------------------------------------------------------------------------------@
    Call func_run("printargs")
    Call func_run("printargs", 1)
    Call func_run("printargs", 1, "abc")
    Call func_run("printargs", 1, "xyz", 123.456)
End Sub
printargs関数名を引き数にfunc_run関数を呼出します。4回呼出しを行い、それぞれ引数なし~引き数4つまで指定しています。


Sub func_run(a_func, ParamArray a_args())
    '@name      run関数起動ラッパ
    '@param     a_func      適用関数
    '@parama    a_args      引数群
    '@refurl    https://excel-ubara.com/excelvba4/EXCEL_VBA_443.html
    '@note
    '   run関数のラッパ関数には任意の個数を取るためにはParamArrayを使用するのがしぜん。しかし、
    '   run関数はoptional形式で最大30個の引き数を取るためにラッパ関数の引き数である配列(上記
    '   「引き数群」)からrun関数の引き数であるoptional形式への変換をどうするかが問題であった。
    '   旧来は引数群の長さを調べて引数個似対応した
    '       run(func)
    '       run(func, arg1)
    '       run(func, arg1, arg2,...argN)
    '   を制御構文にて振り分けていた。しかし、上記URLにて参照不可を渡せばこの制限をパスできる
    '   との情報があり試してみた所うまく行った。
    '   この手法はたぶん他の組み込み関数にも適用できると思われる。
    '@-----------------------------------------------------------------------------------------@
    Dim args: args = a_args
    Call unref_adder(args, 30)
    Call Run(a_func, _
        args(0), args(1), args(2), args(3), args(4), args(5), args(6), args(7), args(8), args(9) _
        , args(10), args(11), args(12), args(13), args(14), args(15), args(16), args(17), args(18), args(19) _
        , args(20), args(21), args(22), args(23), args(24), args(25), args(26), args(27), args(28), args(29))
End Sub
func_run関数はrun関数のラップ関数です。この関数で受け取った引数群(呼び出し側はスカラー値の並び、受け取り側はParamArrayでパックされた配列として受け取ります)をどのようにrun関数に渡せるか?ということを検証していきます。

ポイントはunref_addr関数でrun関数の最大の引き数である30個まで受け取った引数配列(args)を拡張していることです。拡張にあたり埋める値が「参照不可変数」となります。

参照不可変数で埋めることにより、run関数を必要な個数で指定し残りは省略した形で呼出したことと同じ効果が得られます。

どうしてこれが便利かというと引数群がいくつであっても常にrun関数呼び出しが30個の引き数となるのでrun関数を引き数固定で呼出しができるとということです。