Имитация оператора IN

Как можно добиться:

if X in (1,2,3) then

вместо:

if x=1 or x=2 or x=3 then

Другими словами, как лучше всего имитировать оператор IN в VBA для Excel?


person Allan Bowe    schedule 01.10.2009    source источник


Ответы (7)


Я не думаю, что есть очень элегантное решение.

Однако вы можете попробовать:

If Not IsError(Application.Match(x, Array("Me", "You", "Dog", "Boo"), False)) Then

или вы можете написать свою собственную функцию:

Function ISIN(x, StringSetElementsAsArray)
    ISIN = InStr(1, Join(StringSetElementsAsArray, Chr(0)), _
    x, vbTextCompare) > 0
End Function

Sub testIt()
    Dim x As String
    x = "Dog"
    MsgBox ISIN(x, Array("Me", "You", "Dog", "Boo"))
End Sub
person Kredns    schedule 01.10.2009
comment
Не могли бы вы просто избежать этой функции и использовать что-то вроде: InStr(1,"MeYouDogBoo",x)? - person redOctober13; 09.05.2017
comment
@redOctober13 redOctober13 это может сработать, если вы разделите элементы списка разделителем, который не может быть найден в x. В противном случае YouDo вызовет срабатывание InStr. - person mrdaddychops; 17.01.2018
comment
Будьте осторожны с этой простой версией функции IsIn(). Он вернет True, если искомое слово содержится в любых словах в переданном массиве. Поиск «делать» вернет true, потому что он найден в «Собаке». Лучший способ — убедиться, что chr(0) находится до и после искомого слова, а также до и после объединенной строки поиска. Пример можно найти здесь ‹freevbcode.com/ShowCode.asp?ID=1675> - person Ben; 19.04.2018
comment
@Ben, ты можешь проверить эту ссылку, похоже, она не работает. Также я написал этот ответ почти 10 лет назад, и вы правы, что его можно улучшить. - person Kredns; 30.04.2018
comment
При тестировании этот метод занял 1,828 секунды, а этот ответ занял всего 0,406 секунды. (Подробности в другом ответе.) - person ashleedawg; 27.08.2018

Вы также можете попробовать оператор CASE вместо IF.

Select Case X

 Case 1 To 3   
  ' Code to do something
 Case 4, 5, 6
  ' Code to do something
 Case 7
  ' Code to do something
 Case Else  
  ' More code or do nothing

End Select
person Robert Mearns    schedule 02.10.2009
comment
Как это короче, чем if x=1 or x=2 or x=3 then, как спросил ОП? - person ashleedawg; 27.08.2018
comment
Я думаю, что это все еще хороший ответ и мой предпочтительный вариант. Вам нужен только один оператор case, так как значения могут складываться: Select Case x Case 1,2,3 ' Your code... End Select - person LiceRewis; 03.04.2019

Самый быстрый метод:

Here's a method much faster and more compact than any of the other answers, and works with numeric or text values:

Function IsIn(valCheck, valList As String) As Boolean  
    IsIn = Not InStr("," & valList & ",", "," & valCheck & ",") = 0
End Function

Примеры:

Используйте IsIn с числовым значением:

Sub demo_Number()
    Const x = 2
    If IsIn(x, "1,2,3") Then
        Debug.Print "Value " & x & " was Found!"
    Else
        Debug.Print "Value " & x & " was not Found."
    End If
End Sub

Используйте IsIn со строковым значением:

Sub demo_Text()
    Const x = "Dog"
    If IsIn(x, "Me,You,Dog,Boo") Then
        Debug.Print "Value " & x & " was Found!"
    Else
        Debug.Print "Value " & x & " was not Found."
    End If
End Sub

Сравнение скорости:

Чтобы сравнить скорость, я провел тест из принятого ответа 100 000 раз:

  • 0.406 sec (FASTEST) Эта функция (используя InStr):
  • 1.828 sec (450% slower) Принят Ответ с функцией "ISIN"
  • 1.799 sec (440% slower) Ответ с "IsInArray" из freeVBcode
  • 0.838 sec (206% slower) Ответ с измененной функцией "IsInArray"

Я не включил гораздо более длинный ответ, в котором используется SELECT..CASE, поскольку целью ОП, предположительно, было упрощение и сокращение< /em> задача по сравнению с "if x=1 or x=2 or x=3 then".

person ashleedawg    schedule 27.08.2018
comment
Зачем усложнять свою функцию лишними Not и = 0? - person Excel Hero; 02.05.2020

ты пробовал

eval("3 in(1,2,3,4,5)")
person THEn    schedule 01.10.2009
comment
Я получаю подпрограмму или функцию, которая не определена - не знаю, связано ли это с тем, что я нахожусь в VBA (не в VB)? отредактировал вопрос... - person Allan Bowe; 01.10.2009
comment
Это функция Access VBA. Извините, я не видел, что вы упомянули Excel VBA. - person THEn; 01.10.2009
comment
... так что это не ответ на этот вопрос. Почему он все еще здесь? - person ashleedawg; 27.08.2018

Нет ни одного, о котором я знаю.

Обычно я использую самодельную функцию InArray(), например, на http://www.freevbcode.com/ShowCode.asp?ID=1675

Вы также можете сделать версию, которая перебирает массив вместо объединения, если это больше подходит для вашего типа данных.

person anschauung    schedule 01.10.2009
comment
При тестировании этот метод занял 1,799 секунды, в то время как этот ответ занял всего 0,406 секунды. - person ashleedawg; 27.08.2018

Это не работает без написания собственной функции. Имейте в виду, что принятое решение @Kredns может не работать должным образом для всех типов объектов, поскольку они принудительно преобразуются в строки (что также может вызывать ошибки несоответствия типов).

Это решение должно (надеюсь) обрабатывать все типы данных (по крайней мере, в Excel 365, не уверен насчет более ранних версий):

Function IsIn(x As Variant, list As Variant) As Boolean
    ' Checks whether list (Array) contains the element x
    IsIn = False
    For Each element In list
        If x = element Then IsIn = True
    Next element
End Function
person ascripter    schedule 30.07.2021

Я написал это сейчас...

Public Function IsInArray(FindValue As Variant, ParamArray arrEmailAttachment()) As Boolean

Dim element As Variant

For Each element In arrEmailAttachment
    If element = FindValue Then
        IsInArray = True
        Exit Function
    End If
Next element

IsInArray = False

End Function
person shlomo    schedule 10.10.2016
comment
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и/или как этот код отвечает на вопрос, повышает его ценность в долгосрочной перспективе. - person ashleedawg; 27.08.2018
comment
При тестировании этот метод занял 0,838 секунды, в то время как этот ответ занял всего 0,406 секунды< /б>. - person ashleedawg; 27.08.2018