Exit a while loop in VBS/VBA - vba

Is there a method of exiting/breaking a while in VBS/VBA?
Following code won't work as intended:
num = 0
while (num < 10)
if (status = "Fail") then
exit while
end if
num = num+1
wend

VBScript's While loops don't support early exit. Use the Do loop for that:
num = 0
do while (num < 10)
if (status = "Fail") then exit do
num = num + 1
loop

what about changing the while loop to a do while loop
and exit using
Exit Do

While Loop is an obsolete structure, I would recommend you to replace "While loop" to "Do While..loop", and you will able to use Exit clause.
check = 0
Do while not rs.EOF
if rs("reg_code") = rcode then
check = 1
Response.Write ("Found")
Exit do
else
rs.MoveNext
end if
Loop
if check = 0 then
Response.Write "Not Found"
end if}

Incredibly old question, but bearing in mind that the OP said he does not want to use Do While and that none of the other solutions really work... Here's something that does exactly the same as a Exit Loop:
This never runs anything if the status is already at "Fail"...
While (i < 20 And Not bShouldStop)
If (Status = "Fail") Then
bShouldStop = True
Else
i = i + 1
'
' Do Something
'
End If
Wend
Whereas this one always processes something first (and increment the loop variable) before deciding whether it should loop once more or not.
While (i < 20 And Not bShouldStop)
i = i + 1
'
' Do Something
'
If (Status = "Fail") Then
bShouldStop = True
End If
Wend
Ultimately, if the variable Status is being modified inside the While (and assuming you don't need i outside the while, it makes no difference really, but just wanted to present multiple options...

I know this is old as dirt but it ranked pretty high in google.
The problem with the solution maddy implemented (in response to rahul) to maintain the use of a While...Wend loop has some drawbacks
In the example given
num = 0
While num < 10
If status = "Fail" Then
num = 10
End If
num = num + 1
Wend
After status = "Fail" num will actually equal 11. The loop didn't end on the fail condition, it ends on the next test. All of the code after the check still processed and your counter is not what you might have expected it to be.
Now depending on what you are all doing in your loop it may not matter, but then again if your code looked something more like:
num = 0
While num < 10
If folder = "System32" Then
num = 10
End If
RecursiveDeleteFunction folder
num = num + 1
Wend
Using Do While or Do Until allows you to stop execution of the loop using Exit Do instead of using trickery with your loop condition to maintain the While ... Wend syntax. I would recommend using that instead.

While many have mentioned Do While...Loop, there are no examples showing the While is not necessary:
count = 0
Do
count = count + 1
wscript.echo count
If (count > 9) Then
Exit Do
End If
'...Some other logic that can be ended early...
wscript.sleep(1000)
Loop
If you already have the variable to compare against and it makes sense to complete the loop, Do While... is great. However, if you're doing something a little more granular, like the WScript.Sleep above that delays the script can be avoided.

Use Do...Loop with Until keyword
num=0
Do Until //certain_condition_to_break_loop
num=num+1
Loop
This loop will continue to execute, Until the condition becomes true
While...Wend is the old syntax and does not provide feature to break loop! Prefer do while loops

Related

Reset index cycle for-next

Good morning,
I have a problem with the for-next loop. At the second iteration of the cycle, the exit from the cycle occurs even if the exit condition on variable j is not respected. I would have solved the problem with the goTo statement. However I am wondering why index reset does not work in this case.
Thank you.
For j = LBound(AttivitaTemp) To UBound(AttivitaTemp)
If confronta(AttivitaTemp(j), AttivitaFinali) = "#N/D" Then
activityTemp = AttivitaTemp(j)
rigaTemp = confronta(activityTemp, Attivita)
SuccessioniTemp = estrai_riga(MatriceElenchiSuccessioni, rigaTemp)
SuccessioniTemp = cancella_vuoti_vettore(SuccessioniTemp)
ESsuccessioni = EF(rigaTemp)
For k = LBound(SuccessioniTemp) To UBound(SuccessioniTemp)
rigaTemp = confronta(SuccessioniTemp(k), Attivita)
ES(rigaTemp) = Application.WorksheetFunction.Max(ES(rigaTemp), ESsuccessioni)
EF(rigaTemp) = ES(rigaTemp) + Durate(rigaTemp)
Next
VettoreSuccessioniTemp = unisci_vettori(VettoreSuccessioniTemp, SuccessioniTemp)
If j = UBound(AttivitaTemp) Then
AttivitaTemp = VettoreSuccessioniTemp
ReDim VettoreSuccessioniTemp(0)
j = LBound(AttivitaTemp) - 1
'GoTo ricomincia_ciclo_j
End If
End If
Next
Observing the variable j at the second iteration it results j = 0, with the next it goes to j = 1 but the for loop is not re-executed, although UBound (AttivitaTemp) is equal to 1.
In other words, why does this simple cycle work instead, which conceptually does the same thing?
For x = 0 To 2
If x = 2 Then
x = -1
End If
Next
I solved it by myself: the problem is that even if it is possible to reset the iterator, it is not possible to update the conditions of the for loop (the values of "from" and "to" remain "frozen" even if during the loop they are changed).

How to add an if statement inside a for loop in VBA?

For a = 1 to 10
if a = dumm then next a 'this statement should avoid running the subsequent codes if the if statement is true (similar to continue in c++
end if
'statements that need to run when the if statement is not true
next a
Why does this code not work?? It throws compile error: Next without for
Why does this code not work?? It throws compile error: Next without for
Because you have a next without a corresponding For. For/Next and For Each/Next must be paired, you can't open a For loop without a Next and you can't use Next without `For.
Simply:
if a = dumm then a = a + 1
This increments your a value within the loop. I'm unclear as to why you think this isn't applicable, because whether you increment a and then run the code, or skip to the next a (which is functionally equivalent to incrementing it via +1), the result should be same
Or, you could add a label and a GoTo statement:
For a = 1 to 10
if a = dumm then
GoTo MyLabel
end if
'statements that need to run when the if statement is not true
MyLabel:
next a
Or, and my preference, just use proper boolean expressions:
For a = 1 to 10
if not a = dumm Then
'statements that need to run when the if statement is not true
end if
Next
If you don't want to continue the loop at all, then either add an Exit statement,
For a = 1 to 10
if a = dumm Then Exit For
'statements that need to run when the if statement is not true
Next
or use a Do/While loop with proper escape conditions:
a = 1
Do
'statements go here...
a = a + 1
Loop While a <= 10 and Not a = dumm

Don't go into this loop if the array is empty

Til now the method I use to avoid going into for loops which loop through an array which is currently empty is the following:
if len(join(array,"") > 0 then
for i = 1 to ubound(array)
code
next
end if
But this is no joke, I just recently used that line of code if len(join(array,"") > 0 then and that caused the deletion of array and it crashed my program 5 times in a row. I know that sounds hard to believe but here is a screen shot
for some reason the code len(join(array,"") > 0 would destroy the variables2 array. And here is a screen shot that shows that the variables array is clearly full before I go to the bad code: So now I'm trying to use a different code I tried:
if not isempty(array) then
But that's not working. Any ideas?
If Len(Join(greek_act, "")) > 0 Then
For i = 1 To UBound(greek_act)
For j = 1 To UBound(variables2)
If greek_act(i) = variables2(j) Then
variables2(j) = ""
Exit For
End If
Next
Next
variables2 = remove_blanks(variables2)
End If
'variables2 array is full
If Len(Join(greek_letters, "")) > 0 Then
'variables2 array gets destroyed and program crashes here.
For i = 1 To UBound(greek_letters)
rightres1 = Replace(rightres1, greek_letters(i), variables2(i))
Next
End If
Never mind, I decided to just go ahead with the following solution since it appears that the program is temporarily acting up
On Error Resume Next
For i = 1 To UBound(greek_letters)
rightres1 = Replace(rightres1, greek_letters(i), variables2(i))
Next
On Error GoTo 0``
For the Join() technique to work reliably, you must complete the Dimming/ReDimming process:
Sub dural()
Dim greek_ary(1 To 3) As String
s = Join(greek_ary, "")
MsgBox Len(s)
End Sub
Without filling the array, the Len will report 0
Since this is a common test I like to use a reusable function like this:
Function IsArrayEmpty(anArray As Variant)
Dim i As Integer
On Error Resume Next
i = UBound(anArray, 1)
If Err.Number = 0 Then
IsVarArrayEmpty = False
Else
IsVarArrayEmpty = True
End If
End Function
Now in your main Sub do this:
If Not IsArrayEmpty(greek_act) Then
For i = 1 To UBound(greek_act)
For j = 1 To UBound(variables2)
If greek_act(i) = variables2(j) Then
variables2(j) = ""
Exit For
End If
Next
Next
variables2 = remove_blanks(variables2)
End If

For Loop Step -1

I want to know why this loop doesn't show anything in VB.NET.
I think this code will create an infinite loop. But it doesn't show anything.
Dim i as Integer
For i = 1 to 3 Step - 1
MessageBox.Show(i)
Next
Is that loop different with this code (in java/c#) ?
for(int i = 1;i <= 3;i--)
{
// print i
}
http://msdn.microsoft.com/en-us/library/5z06z1kb.aspx
With a negative step size the loop only executes if counter >= end. So in this case with i = 1, that is less than the ending value so the loop doesn't execute at all.
It doesn't show anything because you are running the counter backwards without reversing the start and end conditions.
Think of the loop like this:
Dim counter As Int32 = 1
Do
If counter <= 1 Then
Exit Do
End If
Console.WriteLine("The counter is at " & counter)
counter +=1
Loop
Obviously this won't work properly.
You need to reverse the start and end conditions:
For counter = 3 To 1 Step -1
Console.WriteLine("counter: " & counter)
Next
For i = 1 to 3 Step - 1
It won't create an infinite loop. The loop will simply be skipped, because you can't get from 1 to 3 with a step value of -1.
Is that loop different with this code (in java/c#) ?
This loop will also end immediately, because the initial value (i = 1) meets the exit condition (i <= 3).

Way to Jump to Next i in For..Next Loop?

I'm reverse engineering in QuickBasic and I have code like this:
FOR i = star TO fin
IF a < 1 THEN
CALL clrbot
COLOR 15
PRINT force$(side); " army in "; city$(armyloc(i)); " is CUT OFF !";
TICK turbo!
GOTO alone
END IF
size = size + 1
max = 11: IF LEN(armyname$(i)) < 11 THEN max = LEN(armyname$(i))
mtx$(size) = LEFT$(armyname$(i), max)
array(size) = i
alone:
NEXT i
I'd like to get rid of the line label (alone) and instead do something like:
IF a < 1 THEN
CALL clrbot
COLOR 15
PRINT force$(side); " army in "; city$(armyloc(i)); " is CUT OFF !";
TICK turbo!
NEXT i
END IF
You could replace the GOTO with an Else:
For i = star To Fin
If a < 1 Then
' Do something
Else
' Do Something else
End If
Next
This would follow the same logic - the Else takes the place of the GOTO alone statement.
In the original code (QuickBASIC) if the If block is entered, everything after then GOTO alone statement is ignored.
If the If block is not entered (i.e., a >= 1) then everything after the If block is executed.
The Else statement in the VB.NET code will produce the same behavior. If a < 1, the first block will be executed and the Else block will be ignored, and the loop will advance to the next increment of i.
If a >= 1, then the Else block will be executed and the loop will then advance to the next increment of i.
The above assumes labels in QuickBASIC are like labels in DOS batch files.