Проверка того, является ли значение членом списка

  • Мне нужно проверить часть пользовательского ввода на список элементов; если вход находится в списке элементов, а затем направьте поток в одну сторону. Если нет, направьте поток в другой.
  • Этот список НЕ отображается на листе листа; он должен быть запутан под кодом.

Я подумал о двух стратегиях для этого:

  • Объявить как enum и проверить, является ли вход частью этого enum, хотя я не уверен в синтаксисе для этого - мне нужно инициализировать enum каждый раз, когда я хочу его использовать?
  • Объявить как массив и проверить, является ли вход частью этого массива.

Мне было интересно, что VBA лучше с точки зрения эффективности и удобочитаемости?

Ответ 1

В отличие от языков .NET, VBA не отображает Enum как текст. Это строго число и не существует метода .ToString(), который бы отображал имя Enum. Возможно создать собственный метод ToString() и вернуть представление строки перечисления. Также возможно перечислить тип Enum. Хотя все это достижимо, я бы не рекомендовал делать это таким образом, поскольку все вещи сложны для одной задачи.

Как насчет создания коллекции статей в словаре и просто используйте метод 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, вы сможете использовать intelli-sense с объектом myList, поскольку это было бы ранней заменой на замену

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

с

Dim myList as Dictionary
Set myList = new Dictionary

Это зависит от вас, как вы хотите это сделать и что более удобно. Обратите внимание, что вам не нужно добавлять ссылки, если вы идете с Late Binding, в то время как ссылки требуются, если вы хотите раннее связывание с 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 элемента, чтобы этот пример был как можно более простым. [_Min] и [_Max] указывают минимальное значение и максимальное значение перечисления (его можно настроить, но опять же, пусть это будет просто на данный момент). Вы объявляете, что они оба могут перебирать ваш EList.

ToString() метод возвращает строковое представление Enum. Любой разработчик VBA в какой-то момент понимает, что это слишком плохо, VBA упускает это как встроенную функцию. Во всяком случае, теперь у вас есть собственная реализация.

Exists хранит все userInput, а при повторении через Enum EList соответствует строковое представление вашего Enum. Это излишне, потому что вам нужно вызвать много методов и перебрать перечислимое число, чтобы добиться того, что делает простой метод Dictionary Exists за один раз. Именно поэтому я бы не рекомендовал использовать Enums для вашей конкретной проблемы.

Затем в конце вы можете добавить Main, который просто собирает входные данные от пользователя и вызывает метод Exists. Он показывает окно сообщений с true или false, которое указывает, существует ли строка в виде типа Enum.

Ответ 2

Вы можете запустить простой массив, как показано ниже, где вы добавляете слова в один список:

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

Ответ 3

Просто используйте 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