检查值是否是列表的成员

时间:2014-01-27 10:54:52

标签: excel vba excel-vba

  • 我必须根据项目列表检查一条用户输入;如果输入位于项目列表中,则将流程指向一个方向。如果没有,将流量引导到另一个流量。
  • 此列表 NOT 在工作表本身上可见;它必须在代码下进行模糊处理。

我想到了两种策略:

  1. 声明为enum并检查输入是否是此enum的一部分,虽然我不确定其语法 - 我是否需要每次初始化enum我想用它吗?
  2. 声明为数组并检查输入是否是此数组的一部分。
  3. 我想知道VBA哪个在效率和可读性方面更好?

3 个答案:

答案 0 :(得分:7)

与.NET语言不同,VBA不会将Enum公开为文本。它严格来说是一个数字,没有.ToString()方法可以公开枚举的名称。可以创建自己的ToString()方法并返回枚举的字符串表示形式。也可以enumerate an Enum type。虽然所有这些都是可以实现的,但我不建议这样做,因为对于这样的单一任务来说,过于复杂。

如何创建项目的Dictionary集合,只需使用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 Scripting Runtime库的引用,那么您将能够使用myList对象的智能,因为它本来是早期绑定的替换

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

Dim myList as Dictionary
Set myList = new Dictionary

这取决于你想要的方式和更方便的方式。请注意,如果您使用Late Binding,则不需要添加引用,如果您希望使用智能早期绑定,则不需要引用。


为了让读者能够使用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

首先,您将 列表 声明为枚举。我只为示例添加了3个项目,以尽可能简单。 [_Min][_Max]表示枚举的最小值和最大值(可以调整此值,但是再次,让我们现在保持简单)。您声明它们都可以迭代EList

ToString()方法返回Enum的String表示形式。任何VBA开发人员都会在某种程度上意识到VBA太糟糕了,因为它是一个内置功能。无论如何,你现在已经有了自己的实现。

Exists接受任何userInput存储,并在枚举EList匹配时对着Enum的String表示进行迭代。这是一种矫枉过正,因为你需要调用许多方法并循环遍历枚举,以便能够一次性实现简单的Dictionary Exists方法。这就是为什么我不建议为您的特定问题使用Enums的原因。

然后最后你有Main子,它只是收集用户的输入并调用Exists方法。它会显示一个带有 true false 的消息框,指示字符串是否作为枚举类型存在。

答案 1 :(得分:7)

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

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

或者,如果您想进行更详细的搜索并返回子字符串匹配列表以进行进一步的工作,请使用Filter。如果查找vFilter

,此代码将通过dog返回以下内容
  狗,狗鲨

在这种特殊情况下,代码会检查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

答案 2 :(得分:-1)

只需将Select Case与列表一起使用:

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