Function Foo(thiscell As Range) As Boolean
Foo = thiscell.hasFormula And (InStr(1, UCase(Split(thiscell.formula, Chr(40))(0)), "bar") > 0)
End Function
Эта функция существует для проверки наличия определенной подстроки (bar в этом случае) до (.
Случай, с которым у меня возникают проблемы, - это когда ячейка, переданная в функцию, пуста, thisCell.hasFormula является ложной, но оператор после и все еще оценивается. Это дает мне индекс ошибок вне диапазона во время выполнения.
Действительно ли VBA продолжает оценивать второй аргумент для И, даже если первый был ложным?
То, что вы ищете, называется " оценка короткого замыкания".
У VBA этого нет.
Вы можете увидеть подход, который, вероятно, адаптируется к вашей ситуации здесь.
Подход, выбранный там, заключался в замене a Select Case
на If
. Существует также пример использования вложенных Ifs
.
Как DOK, упомянутый: Нет, VBA не имеет оценки короткого замыкания.
Технически более эффективно использовать операторы 2 If-then
вместо использования оператора AND
, но если вы этого не делаете много раз, вы не заметите сбережений, поэтому идите на то, что более читаемо. И если вы хотите получить действительно технический, VBA обрабатывает несколько операторов If-then
быстрее, чем Select Case
.
VBA причудлива:)
Ответ: да, VBA не проводит оценку короткого замыкания.
Это не просто вопрос стиля; это имеет большое значение в такой ситуации:
If i <= UBound(Arr, 1) And j <= UBound(Arr, 2) And Arr(i, 1) <= UBound(Arr2, 1) Then
Arr2(Arr(i, 1), j) = Arr(i, j)
End If
... что неверно. Более целесообразно:
If i <= UBound(Arr, 1) And j <= UBound(Arr, 2) Then
If Arr(i, 1) <= UBound(Arr2, 1) Then
Arr2(Arr(i, 1), j) = Arr(i, j)
End If
End If
Или, если у вас есть отвращение к вложенным ifs:
If i > UBound(Arr, 1) Or j > UBound(Arr, 2) Then
' Do Nothing
ElseIf Arr(i, 1) > UBound(Arr2, 1) Then
' Do Nothing
Else
Arr2(Arr(i, 1), j) = Arr(i, j)
End If
У VBA есть одно поведение, подобное короткому замыканию.
Обычно Null
распространяется через выражения, например. 3 + Null
- Null
, а True And Null
- Null
.
Однако:
? False And Null
False
Это похоже на поведение короткого замыкания - что происходит? Null
не распространяется, когда другой аргумент конъюнкции (And
) равен False
или 0
- результат равен всего False
или 0
. Неважно, если это левый или правый аргумент. То же самое относится, если другим аргументом для дизъюнкции (Or
) является True
или ненулевое целое число (значение с плавающей запятой округляется до целого с помощью это правило).
Таким образом, побочные эффекты и ошибки не могут быть предотвращены в аргументах And
и Or
, но Null
распространение может быть "закорочено". Это поведение кажется унаследованным от SQL.
A And B
And
. Возможно, вы могли бы лучше объяснить, что вас смущает?
Я думаю, что это лучшая практика:
sub my conditions()
If Condition1=constraint1 then
if Condition2=constraint2 then
if condition3=constraint3 then
...
....
end if
end if
end if
else
end if
....
end if
end sub
Таким образом, вы будете проходить только через условия тогда и только тогда, когда условие я заполнено.
and
в условном выражении «короткозамкнутым», если первое условие было ложным. Вы отвечаете на этот вопрос?
Рассмотрим машинный код, который должен быть запущен. Самый быстрый должен быть по линии сочетания кода вроде...
если sfsf, а затем перейти SkipAB
если fdf затем перешел в
если dffdefedwf, а затем goto MustHave
SkipAB: если dsda > 4, то MustHave
GoneBad: функция выхода
Musthave: ThisIS = true
'сохраняет только несколько моментов, когда программа должна запускать его много тысяч раз... например, поиск файлов на большом диске или когда простой булевский тест используется, чтобы пропустить функцию времени как найти все листы и имена в закрытом листе [Код]
If Not wFF.UsingFileExtMatch Then GoTo SkipExt
If Not wFF.OKFileEXTMatch Then GoTo BADFile
SkipExt: Если не wFF.UsingFileNameMatch, то GoTo SkipFileMatch Если не wFF.OKFileNameMatch Then GoTo BADFile SkipFileMatch: Если не wFF.UsingDaysAgo, то GoTo SkipDaysAgo Если не wFF.OKDaysAgo, то GoTo BADFile SkipDaysAgo:
[/код]
And
VBA не замыкает накоротко, потому что это побитовый оператор, а не логический . См .: stackoverflow.com/questions/8042744/…