VBA 中的“与”是否相同?当第一个参数为 false 时,运算符评估第二个参数?
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 为 false,但是and 后面的语句仍在计算中。这会在运行时产生下标超出范围错误。
即使第一个参数为 false,VBA 是否实际上会继续计算 And 的第二个参数?
Function Foo(thiscell As Range) As Boolean
Foo = thiscell.hasFormula And (InStr(1, UCase(Split(thiscell.formula, Chr(40))(0)), "bar") > 0)
End Function
This function exists to test for the presence of a certain substring (bar, in this case) before the (.
The case I'm having trouble with is when the cell passed into the function is empty, the thisCell.hasFormula is false, but the statement after the and is still being evaluated. This gives me a subscript out of range error in runtime.
Does VBA actually continue evaluating the second argument to the And, even when the first was false?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您正在寻找的称为“短路评估”。
VBA没有这个功能。
您可以在此处查看可能适合您情况的方法。
此处选择的方法涉及用
Select Case
替换If
。还有一个使用嵌套Ifs
的示例。What you are looking for is called "short-circuit evaluation".
VBA doesn't have it.
You can see an approach that is probably adaptable to your situation here.
The approach that was chosen there involved substituting a
Select Case
for theIf
. There is also an example of using nestedIfs
.正如DOK提到的:不,VBA没有短路评估。
从技术上讲,使用 2 个
If-then
语句而不是使用AND
运算符更有效,但除非您多次执行此操作,否则您不会注意到节省的费用,所以选择更具可读性的东西。如果您想真正了解技术,VBA 处理多个If-then
语句的速度也比Select Case
语句更快。VBA 很奇怪:)
As DOK mentioned: No, VBA does not have short-circuit evaluation.
It's technically more efficient to use 2
If-then
statements instead of using theAND
operator, but unless you are doing it a lot of times, you wouldn't notice the savings, so go for whatever is more readable. And if you want to get really technical, VBA handles multipleIf-then
statements faster thanSelect Case
ones as well.VBA is quirky :)
答案是肯定的,VBA 不会短路求值。
这不仅仅是风格问题;在这样的情况下,它会产生很大的不同:
……这是不正确的。更恰当地说:
或者如果您讨厌嵌套的 if:
The answer is yes, VBA does not short circuit evaluation.
It's not just a matter of style; it makes a big difference in a situation like this:
...which is incorrect. More appropriately:
Or if you have an aversion to nested ifs:
VBA 确实有一种类似短路的行为。
通常
Null
通过表达式传播,例如。3 + Null
为Null
,True And Null
为Null
。然而:
这看起来像是短路行为 - 发生了什么?当连词 (
And
) 的另一个参数为False
或0
时,Null
不会传播 - 结果只是False
或0
。无论是左派还是右派争论都没关系。如果析取的另一个参数 (Or
) 为True
或非零整数(浮点值将使用 此规则)。因此,在
And
和Or
的参数中无法防止副作用和错误,但Null
传播可以“短路”。此行为似乎继承自 SQL。VBA does have one short-circuit-like behavior.
Normally
Null
propagates through expressions, eg.3 + Null
isNull
, andTrue And Null
isNull
.However:
This looks like short-circuit behavior - what's going on?
Null
doesn't propagate when the other argument to a conjunction (And
) isFalse
or0
- the result is justFalse
or0
. It doesn't matter if it is the left or right argument. The same applies if the other argument to a disjunction (Or
) isTrue
or a non-zero integer (a floating point value will be rounded to an integer using this rule).So side-effects and errors can't be prevented in arguments to
And
andOr
, butNull
propagation can be "short-circuited". This behavior seems to be inherited from SQL.由于答案是 Google 中排名最高的答案之一,只是在寻找类似
vba if condition not lazy
的内容,我想提供一个更简单的示例,即两个条件的问题和解决方案:AND< /code> 和更有趣的
OR
...(²:我发现最好向其他开发人员解释一下,为什么你不选择
OR
如果他们不知道背景)AND
案例问题:
解决方案:
根据品味、复杂性和可读性,这样写可能是有意义的:
OR
案例问题:
解决方案1:
in-使用
Select
放置不带GoTo
的非冗余单行:以防它应该/必须位于多行上以及其他一些内容:
解决方案 2:
就地、非冗余代码,最少
GoTo
用法,但更冗长If
- 多行代码:解决方案 3:
就地,条件(可能适合)在一行上类似to
OR
- 与相当多的GoTo
用法的连接:解决方案 4:
异地代码 (
Sub
) ,避免GoTo
,条件(可能适合)一行,但模块/类代码可能更难以阅读/分散/混乱:解决方案 5:
使用一个条件变量:
解决方案 6:
使用多个条件变量:
Since the answer is one of the top ranked in Google just looking for something like
vba if condition not lazy
I would like to provide a simpler example, the problem and solutions of both conditions:AND
and the more interestingOR
...(²: I find it better to explain other devs, why you did not choose
OR
if they don't know the background)the
AND
caseproblem:
solution:
Depending on taste, complexity and readability it may make sense to write it this way:
the
OR
caseproblem:
solution 1:
in-place, non-redundant one-liner without
GoTo
usingSelect
:in case it should/must be on multiple lines and with some else:
solution 2:
in-place, non-redundant code with minimal
GoTo
usage, but more lengthyIf
-multi-line code:solution 3:
in-place, conditions (may fit) on one line similar to
OR
-concatenation with quite someGoTo
usage:solution 4:
out-of-place code (
Sub
), avoidingGoTo
, conditions (may fit) on one line, but module/class code may be more unreadable/spread/cluttered:solution 5:
using one condition variable:
solution 6:
using multiple condition variables:
我认为这是最佳实践:
因此,当且仅当满足条件 i 时,您才会通过条件。
I think this is the best practice:
Thus you will be only passaing through conditions if and only if condition i is fullfilled.
考虑必须运行的机器代码。
最快的应该是混合代码,例如...
if sfsf then goto SkipAB
if fdf then goto goneBad
if dffdefedwf then goto MustHave
SkipAB:
如果 dsda > 4 然后 MustHave
GoneBad:
退出函数
必须具备:
ThisIS = true
'仅在程序必须运行时节省一些时间
数千次...例如搜索大驱动器的文件
或者当使用简单的布尔测试来跳过耗时的函数时
就像在封闭的工作表中查找所有工作表和名称一样
[代码]
跳过扩展:
如果不是 wFF.UsingFileNameMatch 则转到 SkipFileMatch
如果不是 wFF.OKFileNameMatch 则转到 BADFile
跳过文件匹配:
如果不是 wFF.UsingDaysAgo 则转到 SkipDaysAgo
如果不是 wFF.OKDaysAgo 则转到 BADFile
跳过DaysAgo:
[/代码]
Consider the machine code that has to run.
The fastest should be along the lines of a mix of code like...
if sfsf then goto SkipAB
if fdf then goto goneBad
if dffdefedwf then goto MustHave
SkipAB:
if dsda > 4 then MustHave
GoneBad:
exit function
MustHave:
ThisIS = true
' only saves a few moments when the program has to run through it
many thousands of times ... eg file searching a large drive
or when a simple Boolean test is used to skip a time consuming function
like finding all the sheets and names in a closed worksheet
[code]
SkipExt:
If Not wFF.UsingFileNameMatch Then GoTo SkipFileMatch
If Not wFF.OKFileNameMatch Then GoTo BADFile
SkipFileMatch:
If Not wFF.UsingDaysAgo Then GoTo SkipDaysAgo
If Not wFF.OKDaysAgo Then GoTo BADFile
SkipDaysAgo:
[/code]