web-dev-qa-db-ja.com

ExcelVBAでの関数のオーバーロードとUDF

ExcelVBAを使用してUDFを作成しています。異なる引数が異なる関数を呼び出すように、いくつかの異なるバージョンで自分のUDFをオーバーロードしたいと思います。

VBAはこれをサポートしていないようですが、同じ目標を達成するための、面倒ではない優れた方法を誰かが提案できますか?オプションの引数を使用する必要がありますか、それともより良い方法がありますか?

28
Patrick

引数を_Optional Variants_として宣言すると、次の例に示すように、IsMissing()を使用して引数が欠落していないかどうかをテストするか、TypeName()を使用して型を確認できます。

_Public Function Foo(Optional v As Variant) As Variant

    If IsMissing(v) Then
        Foo = "Missing argument"
    ElseIf TypeName(v) = "String" Then
        Foo = v & " plus one"
    Else
        Foo = v + 1
    End If

End Function
_

これは、ワークシートから= FOO()= FOO(numberとして呼び出すことができます。 、または= FOO( "string")

51
Joel Spolsky

パラメータ数で区別できる場合は、次のように機能します。

Public Function Morph(ParamArray Args())

    Select Case UBound(Args)
    Case -1 '' nothing supplied
        Morph = Morph_NoParams()
    Case 0
        Morph = Morph_One_Param(Args(0))
    Case 1
        Morph = Two_Param_Morph(Args(0), Args(1))
    Case Else
        Morph = CVErr(xlErrRef)
    End Select

End Function

Private Function Morph_NoParams()
    Morph_NoParams = "I'm parameterless"
End Function

Private Function Morph_One_Param(arg)
    Morph_One_Param = "I has a parameter, it's " & arg
End Function

Private Function Two_Param_Morph(arg0, arg1)
    Two_Param_Morph = "I is in 2-params and they is " & arg0 & "," & arg1
End Function

関数を区別する唯一の方法が型によるものである場合、関数をオーバーライドするC++やその他の言語が行うこと、つまり署名によって呼び出すことを効果的に行う必要があります。通話を次のようにすることをお勧めします。

Public Function MorphBySig(ParamArray args())

Dim sig As String
Dim idx As Long
Dim MorphInstance As MorphClass

    For idx = LBound(args) To UBound(args)
        sig = sig & TypeName(args(idx))
    Next

    Set MorphInstance = New MorphClass

    MorphBySig = CallByName(MorphInstance, "Morph_" & sig, VbMethod, args)

End Function

期待するシグネチャに一致するいくつかのメソッドを使用してクラスを作成します。ただし、おそらくエラー処理が必要になるでしょう。また、認識できるタイプは限られていることに注意してください。たとえば、日付はTypeNameDoubleです。

5
Mike Woodhouse

VBAは散らかっています。偽のオーバーロードを行う簡単な方法があるかどうかはわかりません。

過去に、私は多くのオプションを使用するか、さまざまな機能を使用しました。例えば

Foo_DescriptiveName1()

Foo_DescriptiveName2()

引数リストがばかげていない限り、適切なデフォルトを持つオプションの引数を使用して、ケースを呼び出すための個別の関数を作成すると思います。

0
theo

また、引数リストにバリアントデータ型を使用することを検討し、TypeOfステートメントを使用して何がどの型であるかを把握し、何が何であるかを把握するときに適切な関数を呼び出すこともできます...

0
Jon Fournier