如果已经执行,如何不在循环内输入if语句

时间:2019-01-05 20:05:11

标签: excel vba for-loop if-statement

我有一个for循环,在其中有if语句。

在我的Excel中,我有一个包含一次每个值的列表。一旦找到它,我什至不希望代码甚至检查条件,我希望它在每次执行循环时完全跳过if语句的这一部分,有可能吗?

这是我的代码和清单: Here is my code and list

循环的第一次迭代将发现“ c”是值,因此它将执行其内部的操作(xc = i)

我不希望代码再次检查“ ElseIf Cells(1,i)=“ c”,如下图所示,这可能吗?

what i want

代码为文本:

Sub test()

Dim i, xa, xb, xc As Integer

For i = 1 To 5

    If Cells(i, 1) = "a" Then
      xa = i
    ElseIf Cells(i, 1) = "b" Then
      xb = i
    ElseIf Cells(i, 1) = "c" Then
      xc = i
    End If

Next i

End Sub

4 个答案:

答案 0 :(得分:2)

我对您的需求的最初解释是“如果代码再次击中'c',那就不要采取行动”。

为此,您可以按以下方式修改逻辑:

ElseIf (xc = 0) And (Cells(i, 1) = "c") Then

这样,一旦设置xc,第一个布尔表达式将为False,并且将永远不会再满足整体条件。如@TimWilliams所述,VBA仍将评估第二个布尔表达式,这与其他具有短路选项的语言不同。 @Gene的答案描述了解决此问题的方法。通常,为了获得更好的性能,您应该先评估简单的条件,然后再诉诸昂贵的条件。

附加说明

在VBA中,必须为每个变量指定一个类型。在您的Dim行中,只有xc是一个整数,而其他变量是Variants。

一个不合格的Cells()调用在当前活动的工作表上进行,这可能不是预期的。建议:使用工作表的代号限定Cells()。您可以在工作表的(Name)属性下看到或指定的CodeName(从Visual Basic编辑器中可以看到)。例如,如果(Name)Sheet1,请使用Sheet1.Cells()。仅当代码与Sheet1位于同一工作簿中时,此方法才有效。如果代码位于工作表本身的后面,您甚至可以使用Me.Cells()

当像处理代码一样处理单元格值时,VBA(安静地)很友好,并且了解到Range类的众多属性中,Value是您感兴趣的。但是,最好在Sheet1.Cells(i, j).Value中明确声明目标属性。

编辑

知道这些值将是不同的并且它们中大约有60个,我建议您简单地使用一个Dictionary(如下所示)来一次性获得每个值的行,而不必级联If

Option Explicit

Sub test()
    Dim i As Integer
    Dim dict As Object 'Scripting.Dictionary

    Set dict = CreateObject("Scripting.Dictionary")

    For i = 1 To 5
        dict(Cells(i, 1).Value) = i
    Next

    Debug.Print dict("a") '4
    Debug.Print dict("b") '2
    Debug.Print dict("c") '1
    'Etc.
End Sub

答案 1 :(得分:0)

如果我理解您的问题,可以尝试以下代码:

Sub test()
Dim i, xa, xb, xc As Integer
Dim a, b, c As Boolean

a = False 
b = False
c = False

For i = 1 To 5

    If Cells(i, 1) = "a" And a <> True Then

        xa = i
        a = True
    ElseIf Cells(i, 1) = "b" And b <> True Then

        xb = i
        b = True
    ElseIf Cells(i, 1) = "c" And c <> True Then

        xc = 1
        c = True

    End If

Next i
End Sub

仅当跳过单元格(i,1)=“ a”并跳过下一个“ a”值之后,才将布尔变量设置为true。

希望这会有所帮助

答案 2 :(得分:0)

我想我只是想“修改” Ferdinando的代码,所以它更具“可读性”。此版本与费迪南多(Ferdinando)或Excelosaurus(Excelosaurus)之间的主要(实质性)区别在于,一旦检测到该值,该单元甚至不会进行测试。请记住,问题是:我不希望代码再次检查“ ElseIf Cells(1,i)=” c“ ... 所以,此版本正是这样做的。

Sub test()
Dim i As Integer, xa As Integer, xb As Integer, xc As Integer
Dim aFound As Boolean, bFound As Boolean, cFound As Boolean
Dim r As Range

For i = 1 To 5
    Set r = Cells(i, 1)
    If Not aFound Then
        If r = "a" Then xa = i: aFound = True
    ElseIf Not bFound Then
        If r = "b" Then xb = i: bFound = True
    ElseIf Not cFound Then
        If r = "c" Then xc = i: cFound = True
    End If
Next i
End Sub

答案 3 :(得分:0)

我不喜欢60个ElseIfs的想法。请检查下面的代码。为了对其进行测试,创建一个名为“ TestSheet”的工作表,并将A1:A5输入到单元格H2:H6。

Sub TestSpike()
    ' 06 Jan 2019

    Dim Rng As Range
    Dim Items As Variant
    Dim Spike As String
    Dim Tmp As String
    Dim i As Integer
    Dim R As Long

    Items = Split("c|b|0|a|1", "|")
    With Worksheets("TestSheet").Columns("H")
        For R = 2 To 6
            Tmp = CStr(.Cells(R).Value)
            If InStr(1, Spike, Tmp, vbTextCompare) = 0 Then
                Spike = Spike & "|" & Tmp

                On Error Resume Next
                i = Application.WorksheetFunction.Match(Tmp, Items, 0)
                If Err Then
                    MsgBox Tmp & " wasn't found in Array"
                Else
                    MsgBox "i = " & i & " = Item " & Tmp
                End If
            End If
        Next R
    End With
End Sub

该代码带有“尖峰”。首先根据Spike检查每个项目。如果找到,则不进行进一步测试。否则,它已添加到Spike中。 在将新项目添加到Spike之后,将对可容纳60个元素的数组“ Items”进行检查,这些数组由Chr(124)分隔,因此,Split(“ c | b | 0 | a | 1”,“ |” )。我使用工作表函数MATCH在数组中查找项目。结果是索引号(如果找不到,则为错误)。您可以在Select Case语句中使用此索引号来处理彼此不同的每个项目,基本上与现在If语句返回True时处理它的方式相同。 您可能会发现对这种设置有用的一个想法是使用Match函数的索引从另一个数组返回一个值。例如,另一个数组可能包含函数名称,并且您使用Application.Run为每个项目调用不同的函数。这比检查60多个Select Case语句要快得多。