【问题标题】:how to have multiple optional arguments in a user defined function in VBA/ Excel如何在 VBA/Excel 中的用户定义函数中有多个可选参数
【发布时间】:2018-02-14 23:17:23
【问题描述】:

我需要开发一个 UDF 来根据几个可能的条目检查单元格值,以检查单元格是否等于这些值中的任何一个。如您所见,我对如何进行此检查有一个想法。但是以一种可以接受多个可选条目的方式对函数进行编码对我来说并不清楚。例如,我正在寻找一些动态的东西,比如 EXCEL { CONCATENATE( text1, [ text2, ... text_n ] )} 中的 CONCATENATE。我对带有 5 个可选参数的此类函数的代码如下:

Function IfAmong(TextToCheck As String, Text1 As String, Optional Text2 As String, _ 
    Optional Text3 As String, Optional Text4 As String, Optional Text5 As String,_ 
    Optional text6 As String) As Boolean    
    Dim dd As New Scripting.Dictionary
    dd.CompareMode = TextCompare
       dd.Add Text1, dd.Count
       If Text2 <> "" Then dd.Add Text2, dd.Count
       If Text3 <> "" Then dd.Add Text3, dd.Count
       If Text4 <> "" Then dd.Add Text4, dd.Count
       If Text5 <> "" Then dd.Add Text5, dd.Count
       If text6 <> "" Then dd.Add text6, dd.Count
    IfAmong = dd.Exists(TextToCheck)
    dd.RemoveAll
End Function

我想让它与用户所需的可选条目的数量相关(就像连接一样)。如果可能的话,还可以通过循环自动检查条目。我尝试将文本添加为​​数组,但不起作用!

for i =2 to Ubound(text(i))
     if text(i) <>"" then..........
next

我也无法做到这一点。

感谢和问候, M

【问题讨论】:

    标签: vba excel user-defined-functions


    【解决方案1】:

    使用ParamArrayParamArray 必须始终是要声明的最后一件事,并且必须是 Variant 类型。它将允许您输入任意数量的变量,而无需定义每个变量。

    Function IfAmong(TextToCheck, ParamArray Text() As Variant) As Boolean
        Dim txt As Variant
        Dim dd As New Scripting.Dictionary
    
        dd.CompareMode = TextCompare
    
        For Each txt In Text()
            If Not txt = vbNullString Then dd.Add Key:=txt, Item:=dd.Count
        Next txt
    
        IfAmong = dd.Exists(TextToCheck)
        dd.RemoveAll
    End Function
    

    但是,我会这样做:

    Function IfAmong(TextToCheck, ParamArray Text() As Variant) As Boolean
        Dim txt As Variant
        ' Default value if not found
        IfAmong = False
        For Each txt In Text()
            ' Make sure input is text
            If TypeName(txt) = "String" Then
                ' Test if they're equal ignoring case
                If LCase(txt) = LCase(TextToCheck) Then
                    ' Set to true as found
                    IfAmong = True
                    ' There's no point to keep searching as we've already got our answer so lets exit
                    Exit For
                End If
            End If
        Next txt
    End Function
    

    这样可以避免使用可能导致引用错误的字典。您的函数中的字典也不处理重复值。字典不允许您拥有多个具有相同值的键,因此一旦您有重复的文本值,您的函数就会因为未处理而崩溃。

    【讨论】:

    • 谢谢,好点子。我有一个类似的数组函数例程,所以只是在这里重新应用它。您的代码更好、更高效。高度赞赏。
    • 请注意,dim i 和 next i 中的 i 不是必需的,并且 next i 会导致错误。我编辑了代码,但在申请之前需要同行评审。
    • 你是绝对正确的。我正在使用 For i = LBound(Text) to UBound(Text) 并在更改为 For Each Loop 时忘记更改这些位我将编辑我的答案。好地方
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 2011-02-06
    • 2018-03-25
    • 1970-01-01
    相关资源
    最近更新 更多