Оценивает ли оператор VBA «И» второй аргумент, если первый является ложным? - PullRequest
45 голосов
/ 10 августа 2011
Function Foo(thiscell As Range) As Boolean
  Foo = thiscell.hasFormula And (InStr(1, UCase(Split(thiscell.formula, Chr(40))(0)), "bar") > 0)
End Function

Эта функция существует для проверки наличия определенной подстроки (в данном случае, столбца) перед (.

У меня проблема с тем, что ячейка, переданная в функцию, пуста, thisCell.hasFormula имеет значение false, но оператор после и все еще оценивается. Это дает мне сообщение об ошибке вне диапазона во время выполнения.

Продолжает ли VBA вычислять второй аргумент для И, даже если первый был ложным?

Ответы [ 6 ]

56 голосов
/ 10 августа 2011

То, что вы ищете, называется " оценка короткого замыкания ".

VBA не имеет его.

Вы можете увидеть подход, который, вероятно, можно адаптировать к вашей ситуации здесь .

Выбранный подходтам подразумевалось замена Select Case на If.Также есть пример использования вложенного Ifs.

10 голосов
/ 11 августа 2011

Как упоминалось DOK : Нет, VBA не имеет оценки короткого замыкания.

Технически более эффективно использовать операторы 2 If-then вместо оператора AND,но если вы не делаете это много раз, вы не заметите экономию, так что выбирайте то, что более читабельно.И если вы хотите получить действительно техническую информацию, VBA обрабатывает несколько If-then операторов быстрее, чем Select Case.

VBA - это странно:)

2 голосов
/ 22 мая 2014

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 .

2 голосов
/ 11 мая 2013

Ответ - да, 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
0 голосов
/ 07 января 2017

Я думаю, что это лучшая практика:

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

Таким образом, вы будете проходить через условия только тогда и только тогда, когда условие i выполнено.

0 голосов
/ 30 ноября 2016

Рассмотрим машинный код, который должен работать. Самый быстрый должен быть в соответствии с сочетанием кода, как ...

если sfsf, то перейти к SkipAB

если fdf, то goto пошелПлохо

если dffdefedwf, то перейдите на 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, тогда перейдите к BADFile SkipFileMatch: Если не wFF.UsingDaysAgo, тогда GoTo SkipDaysAgo Если не wFF.OKDaysAgo, то GoTo BADFile SkipDaysAgo:

[/ код]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...