简体   繁体   中英

how to not enter if statement inside a loop if it have been executed

I have a for loop, and inside it i have if statement.

In my Excel I have a list that contains each value one time. Once I found it i don't want the code to even check the conditional, i want it to skip this part of the if statement completely each time the loop is executed, is it possible?

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

the first iteration of the loop will find that "c" is the value so it will do what inside it (xc = i)

I don't want the code to even check "ElseIf Cells(1, i) = "c" again, like the following image, is this possible?

我想要的是

code as text:

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

My initial interpretation of your need was "if the code hits 'c' again, just don't act".

To do so, you could modify the logic as follows:

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

This way, as soon as xc is set, the first boolean expression would be False, and the overall condition would not ever be met again. As mentioned by @TimWilliams, VBA would still evaluate the second boolean expression, unlike other languages that feature short-circuiting options. @Gene's answer describes a way around this. Typically, for better performance, you would evaluate the simple conditions first, before resorting to costly ones.

Additional notes

In VBA, you must give a type to each variable. In your Dim line, only xc is an Integer, while the other variables are Variants.

An unqualified Cells() call operates on the currently active worksheet, which might not be the expected one. Suggestion: qualify Cells() with the CodeName of your worksheet. The CodeName is what you see or specify under a worksheet's (Name) property as seen from the Visual Basic editor. For example, if (Name) is Sheet1 , use Sheet1.Cells() . This will only work if the code resides in the same workbook as Sheet1 . If the code is behind the worksheet itself, you can even use Me.Cells() .

When dealing with cell values as your code does, VBA is (silently) being nice and understands that, among the numerous properties of the Range class, Value is what you are interested in. It is better practice, however, to explicitly state the target property, such as in Sheet1.Cells(i, j).Value .

EDIT

Knowing the values will be distinct and that there are about 60 of them, I suggest you simply use a Dictionary, as shown below, to get each value's row in one go, without a cascade of If s:

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

if i understood your question you can try this code:

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

Boolean variable is setted true for example only when the cells(i,1)="a" and after the next "a" value are skipped...

hope this helps

I just wanted to "mod" Ferdinando's code so it's a bit more "readable", I think. The main (the substantive) difference between this version and Ferdinando's or Excelosaurus' is that the cell is not even tested once the value is detected. Remember that the question was: I don't want the code to even check "ElseIf Cells(1, i) = "c" again... So, this version does exactly that.

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

I don't like the idea of 60 ElseIfs. Please examine the code below. In order to test it, create a worksheet called "TestSheet" and enter your A1:A5 to cells 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

The code has a "Spike". Each item is first checked against the Spike. If it is found there no further tests are carried out. Else, it is added to the Spike. New items, after being added to the Spike, are checked against the Array "Items" which would hold your 60 elements, separated by Chr(124) thus, Split("c|b|0|a|1", "|"). I use the worksheet function MATCH to look for the item in the array. The result is an index number (or an error, if not found). You can use this index number in a Select Case statement to process each item distinct from others, basically the same way as you now process it when the If statement returns True. One idea you may find useful with this kind of setup is to use the index from the Match function to return a value from another array. The other array might, for example, contain function names and you use Application.Run to call a different function for each item. This would run significantly faster than examining 60-odd Select Case statements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM