关于vba:Instr条件不适用于2个或更多条件

Instr condition doesn't work with 2 or more conditions

我在Excel VBA中具有以下INSTR条件,该条件一直都不起作用

1
2
3
4
5
6
7
STR_TEXT="SKU1234 $100/10'  $200/20'"  ' < example string

IF INSTR(STR_TEXT,"/10'") AND INSTR(STR_TEXT,"/20'") THEN
  ' code
ELSE
  ' code
END IF

由于某种晦涩的原因,它似乎无法检查两个条件,因此即使两个条件都匹配,第一个IF似乎也不起作用并转到ELSE。

以下内容确实有效:

1
2
3
4
5
6
7
8
9
STR_TEXT="SKU1234 $100/10'  $200/20'"  ' < example string

IF INSTR(STR_TEXT,"/10'") THEN
       IF INSTR(STR_TEXT,"/20'") THEN
               ' code
       END IF
ELSE
  ' code
END IF

如您所见,如果我将第一个IF上的条件分开,它将起作用。
但是我宁愿将两个条件都放在同一个IF中,因为代码更"干净"。

任何人都知道为什么和/或如何修复它而不必将IF放入另一个IF中?


其他答案指出了最重要的一点,即InStr实际上返回一个字符串在另一个字符串中的数字位置(如果找不到所需的字符串,则返回0)。正如他们所说,您应该在If语句中测试条件<result> > 0。我只想说说您的测试"一直(一直)不起作用"的背后原因是什么。这是陶醉于某些古老的I- <3-BASIC令人敬畏的好机会。

发生的事情是,在这种情况下(有关更多信息,请参见底部的编辑),VBA的And运算符(和Or等)实际上是按位运算符,而不是逻辑运算符。也就是说,如果将两个整数操作数传递给它,它将逐位执行And,然后返回结果整数。例如,42 And 99的计算结果为34,因为(二进制)0101010 And 11000110100010

现在,通常,如果您使用VBA Boolean值,则And就像逻辑运算符一样工作。这是因为在VBA中,常量True等于数字-1,而False等于数字零。因为VBA将-1表示为设置了所有位的二进制数,而将0表示为清除了所有位的二进制数,所以您可以看到二进制运算等效于逻辑运算。 -1 And <something>始终等于相同的<something>。但是,如果您只是将任何旧数字传递给And,您将获得一个数字,并且该数字并不总是等于常数TrueFalse的数值。 >

考虑一个简单的示例(在立即窗口中键入):

1
2
3
4
5
6
7
8
9
10
11
x="abc"
?Instr(x,"a")
 1
?Instr(x,"b")
 2
?Instr(x,"c")
 3
?(Instr(x,"a") and Instr(x,"b"))
 0
?(Instr(x,"a") and Instr(x,"c"))
 1

现在回想一下,VBA的If语句将任何非零数字参数视为与True相同,将零数字参数视为与False相同。将所有这些放在一起时,您会发现以下示例形式的语句:

1
IF INSTR(STR_TEXT,"/10'") AND INSTR(STR_TEXT,"/20'") THEN

有时会选择第一个条件,有时会选择第二个条件,具体取决于搜索字符串中的内容。这是因为有时按位And操作将返回零,有时将返回非零。确切的结果将取决于找到的字符串的确切位置,这显然不是您所期望的。这就是为什么您已经获得建议的细节很重要的原因。

编辑:正如休·艾伦(Hugh Allen)在此评论中指出的:

当第一个为false时,VBA"和"运算符是否会评估第二个参数?

VBA的And运算符实际上返回两个操作数均为BooleanBoolean值。因此,说它是按位运算符并不完全正确。但这是正确的。同样,它可以充当按位运算符的事实确实意味着它不能像"正常"的,纯粹逻辑的运算符一样起作用。例如,因为它必须评估两个操作数以确定它们是否为数字,所以它不能短路。


示例:

1
if instr(str_Text,"/10'") > 0 AND instr(str_text,"/20'") > 0 then

Tim所说的是instr函数返回要搜索的字符串的第一个实例在字符串中的位置。.

因此在您的示例中:instr(str_Text," / 10')返回13。

当VBA读取您的版本instr(str_text," / 10;")(不带> 0)时,它会看到结果不是1(这表示是真的),因此总是命中else。


Instr()返回一个数字结果:如果它是> 0,则测试的字符串包含正在搜索的字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
Sub Test()

    Dim str_text As String

    str_text ="SKU1234 $100/10'  $200/20'" ' < example string

    If InStr(str_text,"/10'") > 0 And InStr(str_text,"/20'") > 0 Then
        MsgBox"Both"
    Else
        MsgBox"Only one, or none"
    End If

End Sub


InStr函数将返回您试图在string中找到的sub-string的索引。

因此,以下内容将提供数值而不是boolean value

1
INSTR(STR_TEXT,"/10'")

要解决此问题,请使用以下命令将给出if条件所要求的Boolean答案:

1
INSTR(STR_TEXT,"/10'") > 0