Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 检查值是否为列表的成员 我必须对照项目列表检查一段用户输入;如果输入在项目列表中,则将流程定向为单向。如果没有,则将流引导到另一个 此列表在工作表本身上不可见;必须在代码下对其进行模糊处理_Vba_Excel - Fatal编程技术网

Vba 检查值是否为列表的成员 我必须对照项目列表检查一段用户输入;如果输入在项目列表中,则将流程定向为单向。如果没有,则将流引导到另一个 此列表在工作表本身上不可见;必须在代码下对其进行模糊处理

Vba 检查值是否为列表的成员 我必须对照项目列表检查一段用户输入;如果输入在项目列表中,则将流程定向为单向。如果没有,则将流引导到另一个 此列表在工作表本身上不可见;必须在代码下对其进行模糊处理,vba,excel,Vba,Excel,我想到了两种策略: 声明为enum并检查输入是否是该enum的一部分,尽管我不确定其语法-是否每次使用该enum时都需要初始化它 声明为数组并检查输入是否是该数组的一部分 我想知道VBA在效率和可读性方面哪个更好?与.NET语言不同,VBA不将枚举公开为文本。严格来说,它是一个数字,并且没有任何.ToString()方法会公开枚举的名称。可以创建自己的ToString()方法并返回枚举的字符串表示形式。也有可能。尽管一切都是可以实现的,但我不建议这样做,因为对于这样一项任务来说,事情过于复杂了

我想到了两种策略:

  • 声明为
    enum
    并检查输入是否是该
    enum
    的一部分,尽管我不确定其语法-是否每次使用该
    enum
    时都需要初始化它
  • 声明为数组并检查输入是否是该数组的一部分
    我想知道VBA在效率和可读性方面哪个更好?

    与.NET语言不同,VBA不将枚举公开为文本。严格来说,它是一个数字,并且没有任何
    .ToString()
    方法会公开枚举的名称。可以创建自己的
    ToString()
    方法并返回枚举的字符串表示形式。也有可能。尽管一切都是可以实现的,但我不建议这样做,因为对于这样一项任务来说,事情过于复杂了

    您可以创建一个项目的字典集合,然后简单地使用
    Exist
    方法和某种错误处理(或简单的if/else语句)来检查列表中是否存在输入框中的任何用户输入

    例如:

    Sub Main()
    
        Dim myList As Object
        Set myList = CreateObject("Scripting.Dictionary")
    
        myList.Add "item1", 1
        myList.Add "item2", 2
        myList.Add "item3", 3
    
        Dim userInput As String
        userInput = InputBox("Type something:")
    
        If myList.Exists(userInput) Then
            MsgBox userInput & " exists in the list"
        Else
            MsgBox userInput & " does not exist in the list"
        End If
    
    End Sub
    
    注意:如果您添加对
    Microsoft脚本运行时
    库的引用,则您将能够使用intelli sense和
    myList
    对象,因为它将在早期绑定

     Dim myList As Object
     Set myList = CreateObject("Scripting.Dictionary")
    

    这取决于你想走哪条路,什么更方便。请注意,如果使用后期绑定,则不需要添加引用,而如果希望使用intelli sense进行早期绑定,则需要添加引用


    为了让读者能够可视化使用Enum的版本,让我演示一下这个机制是如何工作的

    Enum EList
        item1
        item2
        item3
        [_Min] = item1
        [_Max] = item3
    End Enum
    
    Function ToString(eItem As EList) As String
        Select Case eItem
            Case EList.item1
                ToString = "item1"
            Case EList.item2
                ToString = "item2"
            Case EList.item3
                ToString = "item3"
        End Select
    End Function
    
    Function Exists(userInput As String) As Boolean
        Dim i As EList
        For i = EList.[_Min] To EList.[_Max]
            If userInput = ToString(i) Then
                Exists = True
                Exit Function
            End If
        Next
        Exists = False
    End Function
    
    Sub Main()
    
        Dim userInput As String
        userInput = InputBox("type something:")
    
        MsgBox Exists(userInput)
    
    End Sub
    
    首先,将您的列表声明为Enum。为了使示例尽可能简单,我只添加了3项
    [\u Min]
    [\u Max]
    指示枚举的最小值和最大值(可以对此进行调整,但现在让我们保持简单)。您声明它们都可以在
    EList
    上迭代

    ToString()
    方法返回枚举的字符串表示形式。任何VBA开发人员都会在某个时候意识到,VBA缺少这一内置功能太糟糕了。不管怎样,您现在已经有了自己的实现

    Exists
    获取
    userInput
    存储的任何内容,并在枚举中迭代
    EList
    以匹配枚举的字符串表示形式。这太过分了,因为您需要调用许多方法并在枚举上循环,以便能够一次性实现简单的
    字典
    存在的
    方法。这就是为什么我不建议针对您的特定问题使用枚举的主要原因


    最后是
    Main
    sub,它简单地收集用户的输入并调用
    Exists
    方法。它显示一个带有
    true
    false
    的消息框,指示字符串是否以枚举类型存在。

    您可以运行一个简单的数组测试,如下所示,将单词添加到单个列表中:

    Sub Main1()
    arrList = Array("cat", "dog", "dogfish", "mouse")
    Debug.Print "dog", Test("dog")   'True
    Debug.Print "horse", Test("horse") 'False
    End Sub
    
    Function Test(strIn As String) As Boolean
    Test = Not (IsError(Application.Match(strIn, arrList, 0)))
    End Function
    
    或者,如果您想进行更详细的搜索并返回子字符串匹配列表以供进一步工作,请使用
    过滤器
    。如果查找
    dog

    狗,狗鱼

    在这种特殊情况下,代码会检查是否与
    完全匹配

    Sub Main2()
    arrList = Array("cat", "dog", "dogfish", "mouse")
    Debug.Print "dog", Test1("dog")
    Debug.Print "horse", Test1("horse")
    End Sub
    
    Function Test1(strIn As String) As Boolean
    Dim vFilter
    Dim lngCnt As Long
    vFilter = Filter(arrList, strIn, True)
    For lngCnt = 0 To UBound(vFilter)
        If vFilter(lngCnt) = strIn Then
            Test1 = True
            Exit For
        End If
    Next
    End Function
    

    只需在列表中使用
    选择案例

    Select Case entry
       Case item1,item2, ite3,item4 ' add up to limit for Case, add more Case if limit exceeded
          do stuff for being in the list
       Case Else
          do stuff for not being in list
    End Select
    

    我怎么了,是我错过了什么,还是你的
    医生:
    很奇怪?如果字典中不存在用户输入,
    myList.Exists(userInput)
    只返回
    false
    ,并且没有错误触发geredyoure right@simoco发布之前我没有测试代码,忽略了这一点。已经用更简单的答案更新了答案approach@mehowOn似乎表明枚举可以是字符串,否?@SchwitJanwityanujit您正在查看的是Visual Basic引用,而不是VBA,这两种引用不同。@SchwitJanwityanujit我想您已经有了txt文件或Excel中可用的列表了?-我将直接将其作为数组使用。像我这样一行一行地编一本字典是不现实的。不,清单就在一张纸上!好吧,这是一个惊喜:)然后我仍然会用数组将它们添加到一个代码行中,而不是为每个新项目添加一行新代码。很好的答案,但为时已晚——我已经在字典中手动添加了大约100个项目:(.当然,除了所有的手工工作之外,解决方案没有任何问题。将它们存储在数组中是个好主意。稍微修改一下代码,将列表存储在一个带有分隔符的变量中,然后使用
    Split
    创建您的数组用于恢复这篇旧文章,但我想知道我是谁thod(在字典和数组之间)将是最有效、更快的方法。同样在数组中,使用
    应用程序。Match
    比在数组中循环快吗?感谢回答我自己的问题,我发现使用
    Match()
    函数实际上比仅仅迭代(循环)慢得多通过数组。我使用大小为2000的数组进行了测试。在数组中循环的最坏情况是查找最后一项(在索引2000处)。调用
    Match()
    函数和循环5000次后,
    Match()的总时间
    was
    3.746094
    但仅
    1.667969
    用于在数组中循环。这不提供问题的答案。对
    Select Case entry
       Case item1,item2, ite3,item4 ' add up to limit for Case, add more Case if limit exceeded
          do stuff for being in the list
       Case Else
          do stuff for not being in list
    End Select