2008-09-15 14 views
24

J'utilise Excel VBA pour écrire un fichier UDF. Je voudrais surcharger mon propre UDF avec quelques versions différentes afin que différents arguments appellent différentes fonctions. Comme VBA ne semble pas soutenir cela, quelqu'un pourrait-il suggérer une bonne manière, non-désordonnée d'atteindre le même objectif? Devrais-je utiliser des arguments optionnels ou existe-t-il un meilleur moyen?Surcharge de fonction et UDF dans Excel VBA

Répondre

46

Déclarez vos arguments Optional Variants, vous pouvez tester pour voir si elles sont manquantes à l'aide IsMissing() ou vérifier leur type en utilisant TypeName(), comme le montre l'exemple suivant:

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 

Cela peut être appelé à partir d'une feuille de calcul comme = FOO(), = FOO (nombre), ou = FOO ("chaîne").

+0

Merci, cela semble être une bonne façon de le faire. – Patrick

+0

Joel, c'est vraiment toi que nous devrions tous remercier d'avoir Variante en VB/VBA? ;-) – Yarik

+7

Oui. C'était important pour Excel, car nous avions l'impression que tout ce qui pouvait se trouver dans une cellule de feuille de calcul devait pouvoir aller dans une variable de base, sinon le simple fait de lire une cellule prendrait plusieurs lignes de code. –

0

VBA est en désordre. Je ne suis pas sûr qu'il existe un moyen facile de faire de fausses surcharges:

Dans le passé, j'ai utilisé beaucoup d'options ou utilisé diverses fonctions. Par exemple

Foo_DescriptiveName1() 

Foo_DescriptiveName2() 

Je dirais aller avec des arguments optionnels des valeurs par défaut sensibles à moins que la liste d'arguments va devenir stupide, puis créer des fonctions distinctes pour appeler vos affaires.

0

Vous mighta également envisager d'utiliser un type de données variante pour votre liste d'arguments et comprendre ce qui est de quel type utilisant l'instruction TypeOf, puis appeler les fonctions lorsque vous figurez ce qui est ce que ...

3

Si vous pouvez distinguer par le nombre de paramètres, alors quelque chose comme ça fonctionnerait:

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 seule façon de distinguer la fonction est par types, alors vous allez effectivement avoir à faire ce que C++ et d'autres langues avec des fonctions surchargées, qui est d'appeler par la signature. Je vous suggère de faire l'apparence d'appel quelque chose comme ceci:

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 

et la création d'une classe avec un certain nombre de méthodes qui correspondent aux signatures que vous attendez. Cependant, vous aurez probablement besoin d'un traitement d'erreur, et soyez averti que les types reconnaissables sont limités: les dates sont TypeName Double, par exemple.