読者です 読者をやめる 読者になる 読者になる

t-hom’s diary

主にVBAネタを扱っているブログです。

VBA プロシージャのオーバーロード機能(もどき)を自作する

今回のネタは@mmYYmmddさんのつぶやきから生まれた。感謝。

さて、オーバーロードとは。
ふつう、Functionが取れる引数の数や型は固定されていてあまり自由が利かないのだが、引数の数や型によって処理を振り分けたい場合がある。
VariantやOptional、ParamArrayを活用することでこのような処理も可能であるが、一つの関数で処理を振り分けるとごちゃごちゃしてしまいメンテナンス性が落ちる。

これを解決するのがオーバーロードである。オーバーロードとは、引数の数もしくは型が違えば同名のプロシージャをいくつでも作成できる機能で、JavaC#C++などの言語には実装されている。
これを使えばあくまで別の関数として作れるので、複雑にならずにすむ。

残念ながら、VBAにその機能はない。そこで今回はオーバーロード(もどき)を実装してみたい。
業務コードでこれをすると複雑になるだけなので、ライブラリコードでしか使い道はないけど。

まず引数の型を判定するための関数をFunctionプロシージャで作成。

Function GetArgTypeString(ParamArray args()) As String
    Dim ret As String
    For Each x In args
        Select Case True
        Case IsMissing(x): ret = ret & "M"
        Case IsArray(x): ret = ret & "A"
        Case IsObject(x): ret = ret & "O"
        Case TypeName(x) = "String": ret = ret & "S"
        Case IsDate(x): ret = ret & "D"
        Case IsNumeric(x): ret = ret & "N"
        Case Else: ret = ret & "U"
        End Select
    Next
    GetArgTypeString = ret
End Function

この関数にいくつか引数を渡すと、文字列で型が返ってくる。
たとえば、1, #2017/3/5#, "Hello" の順で渡すと、NDSとなる。Number、Date、Stringである。

次に、たとえばAddという関数を作りたい場合、Addに先ほどの文字列をつけた名前で関数を作る。
タイプごとに4つ用意した。

Function AddSSM(a, b)
    AddSSM = a & b
End Function
Function AddSSS(a, b, c)
    AddSSS = a & b & c
End Function
Function AddNNM(a, b)
    AddNNM = a + b
End Function
Function AddDNM(a, b)
    AddDNM = a + b
End Function

そして、渡された引数によって実際の関数へ処理を引き渡すための、窓口となる関数を作る。
これが本来呼び出したいAdd関数。

Function Add(a, b, Optional c)
    Dim typeString As String
    typeString = GetArgTypeString(a, b, c)
    Add = Application.Run("Add" & typeString, a, b, c)
End Function

あとはメインコード。

Sub Main()
    Debug.Print Add(1, 2)
    Debug.Print Add("1", "1a")
    Debug.Print Add(#3/5/2017#, 1)
    Debug.Print Add("A", "B", "C")
End Sub

実行するとこのとおり。

 3 
11a
2017/03/06 
ABC

まぁ使い物になるかどうかはわからないが、私が類似の問題を抱えたときにアイデアの叩き台になればと思い、ここに残しておく。

念押しするが、アプリケーションコードでコレは余計複雑になるだけなのでやめておいたほうが賢明。ただライブラリを書く目的ならこういうのもアリかなと思う。

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。