2008-09-15 40 views
24

Estoy usando Excel VBA para escribir una UDF. Me gustaría sobrecargar mi propia UDF con un par de versiones diferentes para que los diferentes argumentos invoquen diferentes funciones.Sobrecarga de funciones y UDF en Excel VBA

Como parece que VBA no es compatible con esto, ¿podría alguien sugerir una forma buena y no desordenada de lograr el mismo objetivo? ¿Debería usar argumentos opcionales o hay una mejor manera?

Respuesta

46

declarar sus argumentos como Optional Variants, entonces se puede probar para ver si se está perdiendo el uso de IsMissing() o comprobar su tipo usando TypeName(), como se muestra en el siguiente ejemplo:

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 

Esto puede ser llamado desde una hoja de cálculo como = FOO(), = FOO (número), o = FOO ("cadena").

+0

Gracias, eso suena como una buena manera de hacerlo. – Patrick

+0

Joel, ¿es realmente usted a quien todos debemos agradecerle por tener Variant en VB/VBA? ;-) – Yarik

+7

Sí. Era importante para Excel, ya que consideramos que todo lo que podría ir en una celda de hoja de cálculo debería poder ir en una variable Básica, de lo contrario, el simple acto de leer una celda tomaría varias líneas de código. –

0

VBA is messy. No estoy seguro de que exista una manera fácil de realizar sobrecargas falsas:

En el pasado, he utilizado muchos Opcionales o he utilizado funciones variadas. Por ejemplo

Foo_DescriptiveName1() 

Foo_DescriptiveName2() 

Yo diría que ir con argumentos opcionales que tienen parámetros por defecto a menos que la lista de argumentos se va a poner estúpida, a continuación, crear funciones separadas al que llamar en su caso.

0

Usted Mighta también desea considerar el uso de un tipo de datos de variante para su lista de argumentos y luego averiguar qué es qué tipo es mediante la instrucción TypeOf, y luego llamar a las funciones apropiadas cuando a averiguar qué es lo que ...

3

Si se puede distinguir por el recuento de parámetros, entonces algo como esto funcionaría:

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 

Si la única manera de distinguir la función está por tipos, entonces usted va efectivamente a tener que hacer lo que C++ y otros lenguajes con funciones anuladas, que es llamar por firma. Yo sugeriría haciendo que el llamado algo como esto:

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 

y la creación de una clase con una serie de métodos que responden a las firmas que se pueden esperar. Sin embargo, es probable que necesite algún tipo de manejo de errores, y tenga en cuenta que los tipos que son reconocibles son limitados: las fechas son, por ejemplo, TypeName Double.