2016-11-17 2 views
1

Есть ли оператор VBA, который проверяет, соответствует ли какой-либо из аргументов значение true? Мне не нравится синтаксис необходимости писать And или Or столько раз для нескольких аргументов, особенно для кнопок, которые имеют функцию «выбрать все/отменить выбор всех».VBA «Любой» логический оператор

Ex.

If checkbox1 = True Or checkbox2 = True or ... checkbox10 = True Then 

Может ли это быть написана более сжато, как

If Any(checkbox1, checkbox2 , ..., checkbox10) Then 

?

Кроме того, есть ли какие-либо соображения производительности для написания такого длинного оператора if? Я заметил, что после добавления этого макроса или кода VBA моя форма доступа загружается медленнее, не знаю, имеет ли это какое-либо отношение к этому.

EDIT

Я попытался тестирования предложенный ниже код

Public Sub text_x() 
Dim a, b, c, d, e, f, g, h, i, result As Boolean 
Dim t1, t2 As Single 

a = False 
b = False 
c = False 
d = False 
e = False 
f = False 
g = False 
h = False 
i = True 

t2 = Timer 
For i = 1 To 10000000 
    result = False 
    If a Or b Or c Or d Or e Or f Or g Or h Or i Then 
      result = True 
    Else 
      result = False 
    End If 
Next 
t2 = Timer - t2 


t1 = Timer 
For i = 1 To 10000000 
    result = False 
    Select Case True 
     Case a, b, c, d, e, f, g, h, i 
      result = True 
     Case Else 
      result = False 
    End Select 
Next 
t1 = Timer - t1 


MsgBox ("Timer1 " & t1 & vbCrLf & "Timer2 " & t2) 
End Sub 

Однако время зависит от того, какой я поставил первый в коде (t1 или t2). Почему это?

+0

отбросить '=' часть. вы также можете сохранить их в массиве. –

+0

Вы можете хранить элементы управления в массивах? –

+1

да почему бы и нет ???? –

ответ

2

Вы можете приблизить это с Case переключателем, что-то вроде:

Select Case True 
    Case CheckBox1, CheckBox2, CheckBox3, ... CheckBox10 '# Be sure to enumerate ALL of the CheckBoxes here 
     MsgBox "any" 
    Case Else 
     MsgBox "not" 
End Select 

Это немного легче читать/сохранить, чем огромный IF заявление, но не какой-либо эквивалент Any функции в VBA, изначально.

(Вы можете использовать это, чтобы проверить его)

Sub x() 
Dim a, b, c 

a = False 
b = True 
c = False 


Select Case True 
    Case a, b, c 
     MsgBox "any" 
    Case Else 
     MsgBox "not" 
End Select 

End Sub 
+0

Я попытался проверить время этого кода (отредактировано выше), но по какой-то причине время быстрее для того или другого в зависимости от того, какой из них я поставил первым (они оба скомпилируются в один и тот же код?) –

+0

@AllenWang - If вы публикуете это как новый вопрос, я могу пролить свет на него. – Comintern

+0

@Comintern ok сделает –

3

Это довольно легко просто свернуть свой собственный. Обратите внимание, что Any - это ключевое слово, таким образом, имя функции.

Private Function AnyTrue(ParamArray args() As Variant) As Boolean 
    Dim i As Long 
    For i = LBound(args) To UBound(args) 
     If CBool(args(i)) Then 
      AnyTrue = True 
      Exit Function 
     End If 
    Next 
End Function 

Sub SampleUse() 
    Debug.Print AnyTrue(False, False, True, False) 
    Debug.Print AnyTrue(False, False, False) 
End Sub 
+0

, вероятно, хочет добавить 'If Not IsNull (args (i)) И Not IsObject (args (i)) Затем' * before * с помощью 'CBool', чтобы поймать неожиданные значения Variant. – ThunderFrame

3

Я бы это осуществил. Кроме того вы не можете назвать это Any, потому что зарезервирован, так как об этом:

Public Function IsAnyTrue(ParamArray values()) As Boolean 
    Dim i As Long 
    For i = LBound(values) To UBound(values) 
     If CBool(values(i)) Then 
      IsAnyTrue = True 
      Exit Function 
     End If 
    Next 
End Function 

И в то время как мы на это:

Public Function IsAllTrue(ParamArray values()) As Boolean 
    Dim result As Boolean 
    result = True 
    Dim i As Long 
    For i = LBound(values) To UBound(values) 
     result = result And CBool(values(i)) 
     If Not result Then Exit Function 
    Next 
    IsAllTrue = result 
End Function 

Логические операторы (And, Or, ...) не короткое замыкание в VBA (в VB.NET они добавили закорачивание AndAlso и OrElse для этого), поэтому, если вы оценка 20 условий, например:

If expr1 And expr2 And expr3 And ... And exprN Then 

Даже если expr1 оценивает False, VBA будет еще оценивает все до exprN, чтобы определить результат булевого выражения.

Однако с этим:

If IsAnyTrue(expr1, expr2, expr3, ..., exprN) Then 

Вы выручать, как только вы знаете, один True, и с этим:

If IsAllTrue(expr1, expr2, expr3, ..., exprN) Then 

Вы выручать, как только вы знаете, один - False, что повышает производительность.

... И выглядит более аккуратно, чем блок Select Case.

+0

Какой смысл для CBool ​​в вашей второй функции, и почему вы настраиваете логическое сравнение с результатом «result = result» и «CBool» (значения (i)) вместо того, чтобы настроить его в первой функции? Разве вы не можете просто 'If Not CBool ​​(значения (i)) Тогда result = False; Exit Function'? –

+2

'CBool' делает явное преобразование в' Boolean'; из-за 'ParamArray', все элементы являются неявными' Variant' - и мне нравятся мои преобразования типов в явном виде, это все. Спасибо за ping, я написал их в поле ответа без тестирования, второй не возвращался вообще (исправлено). Я нахожу 'result = result И CBool ​​(values ​​(i))' более явный о том, что происходит, - я делаю "return true, если все верно", например 'IsAllTrue', вместо" return false when one is false ", который действительно эквивалентны. Никогда не существует Истинного Пути, чтобы что-либо сделать! –

Смежные вопросы