循环遍历变量数组时是否不能将If语句与多个条件(AND / OR)一起使用?

Cyr*_*ril 6 excel vba loops if-statement variant-array

背景:

在使用某些变体数组将数据根据条件分类到多个位置时,我注意到每次使用if语句将多个条件标记为false。这是用来创建字典的,尽管它从未涉及字典方面,因为仅在变量数组中循环时,响应错误。

我将它们移到两个单独的if语句中,并且一切正常。


题:

为什么在遍历变量数组中的数据时无法使用多条件if语句?


有问题的代码:

生成变体数组的通用代码:

Public ex_arr As Variant, ex_lr As Long, ex_lc As Long
Public dc As Scripting.Dictionary 

Private Sub capture_export_array()
    With Sheets("export")
        ex_lc = .Cells(1, .Columns.Count).End(xlToLeft).Column
        ex_lr = .Cells(.Rows.Count, ex_lc).End(xlUp).Row
        ex_arr = .Range(.Cells(1, 1), .Cells(ex_lr, ex_lc)).Value
    End With
End Sub
Run Code Online (Sandbox Code Playgroud)

导致False条件的代码(立即窗口打印= 0):

Private Sub find_unique_items()
    Set dc = New Scripting.Dictionary
    Dim i As Long
    For i = LBound(ex_arr) To UBound(ex_arr)
        If InStr(ex_arr(i, ex_lc), "CriteriaA") And InStr(ex_arr(i, 4), "CriteriaB") Then dc(ex_arr(i, 2)) = ex_arr(i, 3)
    Next i
    Debug.Print dc.Count
End Sub
Run Code Online (Sandbox Code Playgroud)

产生所需输出的代码(立即窗口打印> 0):

Private Sub find_unique_items()
    Set dc = New Scripting.Dictionary
    Dim i As Long
    For i = LBound(ex_arr) To UBound(ex_arr)
        If InStr(ex_arr(i, ex_lc), "CriteriaA") Then
            If InStr(ex_arr(i, 4), "CriteriaB") Then dc(ex_arr(i, 2)) = ex_arr(i, 3)
        End If
    Next i
    Debug.Print dc.Count
End Sub
Run Code Online (Sandbox Code Playgroud)

Mat*_*don 11

InStr返回一个索引。作为逻辑运算符And要具有Boolean操作数。给定Integer操作数,And运算符是按位运算符 -实话说,这些运算符始终是按位运算符;当操作数为时,我们就将它们称为“逻辑”运算符Boolean

If InStr(ex_arr(i, ex_lc), "CriteriaA") Then
Run Code Online (Sandbox Code Playgroud)

此条件Boolean利用了任何非零值都将转换为的事实,从而隐式地将返回的索引强制为表达式True

当您将逻辑/按位运算符引入方程式时,问题就开始了。

If InStr(ex_arr(i, ex_lc), "CriteriaA") And InStr(ex_arr(i, 4), "CriteriaB") Then dc(ex_arr(i, 2)) = ex_arr(i, 3)
Run Code Online (Sandbox Code Playgroud)

说第一个InStr返回2,第二个返回1。该If表达式变为If 2 And 1 Then,所以0。那是零,所以条件是假的。

等一下

想想2与1的二进制表示形式:

  2:  0010
  1:  0001
AND:  0000
Run Code Online (Sandbox Code Playgroud)

0由于所有位都没有排队,因此按位与运算会产生。


停止滥用隐式类型转换,并明确说明您的真正意思。您的意思是:

If (InStr(ex_arr(i, ex_lc), "CriteriaA") > 0) And (InStr(ex_arr(i, 4), "CriteriaB") > 0) Then dc(ex_arr(i, 2)) = ex_arr(i, 3)
Run Code Online (Sandbox Code Playgroud)

(多余的括号仅用于说明目的)

现在,这将计算两个Boolean表达式,对这两个值进行按位与运算,并按预期正确运行。

True: 1111
True: 1111
 AND: 1111
Run Code Online (Sandbox Code Playgroud)

  • @dwirony`If 2 and 1 Then`不会变成`If True和True那么`,因为`2 And 1`是一个完全有效的可评估表达式。确实会发生向Boolean的转换,但是*在*之后,按位运算得以解决。“ If 2 And 1 Then”解析为“ If 0 Then”,即“ If False Then”。 (2认同)
  • @dwirony如果Instr返回TRUE,这不是问题,但是它返回Long,这就是为什么应该总是一个明确的原因。如果函数像IsError()或IsNumeric一样返回TRUE / FALSE,则可以忽略= True。 (2认同)