检查一个值是否是一个列表的成员

  • 我必须根据项目列表检查一段用户input; 如果input在项目列表中,则单向指导stream程。 如果不是,将stream量引导到另一个。
  • 该列表在工作表本身上可见; 它必须在代码下被混淆。

我曾想过两个策略来做到这一点:

  1. 声明为一个enum并检查input是否是这个enum一部分,虽然我不确定在这个语法 – 我需要初始化enum每次我想要使用它?
  2. 声明为一个数组,并检查input是否是这个数组的一部分。

我想知道VBA在效率和可读性方面更好吗?

与.NET语言不同,VBA不会将Enum作为文本公开。 它严格来说是一个数字,并没有.ToString()方法,将公开名称的枚举。 可以创build自己的ToString()方法并返回一个枚举的string表示forms。 枚举Enumtypes也是可能的。 虽然一切都是可以实现的,但是我不会推荐这样做,因为事情太复杂了。

你如何创build一个项目的Dictionary集合,并简单地使用Exist方法和某种error handling( 或简单的if / else语句 )来检查input框中的任何用户input是否存在于列表中。

例如:

 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对象的智能感,因为它已经被早期绑定replace

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

 Dim myList as Dictionary Set myList = new Dictionary 

这取决于你想要什么方式,什么是更方便。 请注意,如果使用Late Binding,则不需要添加引用,而需要引用的情况下,如果要使用智能检测的Early 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 

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

ToString()方法返回Enum的string表示forms。 任何VBA开发人员在某种程度上意识到这是糟糕的VBA缺less这个内置function。 无论如何,你现在已经有了自己的实现。

Exists获取任何userInput存储,同时迭代Enum EList与Enum的String表示EList匹配。 这是一个矫枉过正,因为你需要调用许多方法,并遍历枚举,以便能够实现一个简单的DictionaryExists方法一次完成。 这主要是为什么我不会推荐使用枚举为您的具体问题。

然后最后你有Main子,它简单地收集用户的input并调用Exists方法。 它显示一个消息框,其中包含truefalse ,表示string是否作为Enumtypes存在。

您可以像下面那样运行一个简单的数组testing,将单词添加到单个列表中:

 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 

或者,如果您想进行更详细的search,并返回子string匹配列表以供进一步工作,请使用“ Filter 。 如果查找dog此代码将通过vFilter返回以下内容

狗,angular鲨

在这个特定的情况下,代码然后检查一个完全匹配的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与一个列表:

 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