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
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").
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.
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 ...
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.
Merci, cela semble être une bonne façon de le faire. – Patrick
Joel, c'est vraiment toi que nous devrions tous remercier d'avoir Variante en VB/VBA? ;-) – Yarik
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. –