Перегрузка функций и UDF в Excel VBA
-
09-06-2019 - |
Вопрос
Я использую Excel VBA для записи UDF.Я хотел бы перегрузить свой собственный UDF несколькими разными версиями, чтобы разные аргументы вызывали разные функции.
Поскольку VBA, похоже, не поддерживает это, может ли кто-нибудь предложить хороший, не запутанный способ достижения той же цели?Должен ли я использовать необязательные аргументы или есть лучший способ?
Решение
Объявляйте свои аргументы следующим образом 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(число), или =FOO("строка").
Другие советы
Если вы можете различать по количеству параметров, то сработало бы что-то вроде этого:
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
и создание класса с несколькими методами, которые соответствуют сигнатурам, которые вы ожидаете.Однако вам, вероятно, потребуется некоторая обработка ошибок, и имейте в виду, что количество распознаваемых типов ограничено:например, даты имеют тип Double.
VBA - это грязно.Я не уверен, что есть простой способ сделать поддельные перегрузки:
В прошлом я либо использовал множество опций, либо использовал различные функции.Например
Foo_DescriptiveName1()
Foo_DescriptiveName2()
Я бы посоветовал использовать необязательные аргументы, которые имеют разумные значения по умолчанию, если только список аргументов не станет глупым, затем создайте отдельные функции для вызова в ваших случаях.
Возможно, вы также захотите рассмотреть возможность использования вариантного типа данных для вашего списка аргументов, а затем выяснить, что к какому типу относится, используя оператор TypeOf, а затем вызвать соответствующие функции, когда вы выясните, что к чему...