VBA - wie man eine for-Schleifeniteration bedingt überspringt

101

Ich habe eine for-Schleife über ein Array. Ich möchte eine bestimmte Bedingung in der Schleife testen und mit der nächsten Iteration fortfahren, wenn dies zutrifft:

For i = LBound(Schedule, 1) To UBound(Schedule, 1)
    If (Schedule(i, 1) < ReferenceDate) Then
        PrevCouponIndex = i
        Continue   '*** THIS LINE DOESN'T COMPILE, nor does "Next"
    End If
    DF = Application.Run("SomeFunction"....)
    PV = PV + (DF * Coupon / CouponFrequency)
Next

Ich weiß, ich kann:

 If (Schedule(i, 1) < ReferenceDate) Then Continue For

Ich möchte jedoch in der Lage sein, den letzten Wert von i in der Variablen PrevCouponIndex aufzuzeichnen.

Irgendwelche Ideen?

Vielen Dank

Richard H.
quelle
3
Sie sagten: "Ich weiß, ich kann: If (Schedule(i, 1) < ReferenceDate) Then Continue For" Sind Sie sich da sicher? Continueist kein VBA-Schlüsselwort.
mwolfe02
@ mwolfe02 - nicht sicher, aber in Beispielen irgendwo gesehen (cpearson?)
Richard H
Möglicherweise war dies ein VB.NET-Beispiel
Anonymer Typ

Antworten:

31

Könnten Sie nicht einfach so etwas machen?

For i = LBound(Schedule, 1) To UBound(Schedule, 1)
  If (Schedule(i, 1) < ReferenceDate) Then
     PrevCouponIndex = i
  Else
     DF = Application.Run("SomeFunction"....)
     PV = PV + (DF * Coupon / CouponFrequency)
  End If
Next
Brian
quelle
4
Genau das habe ich getan :) Aber es nervt mich trotzdem, dass ich Sachen in das Else-Stück einwickeln muss. Vielen Dank
Richard H
4
+1 @RichardH Nun, Sie müssen ein IFfür den Test verwenden, damit dies im Code nicht so teuer ist. Sie sollten jedoch sicherstellen, dass das häufigste Ergebnis Schedule(i, 1)weniger ist, als ReferenceDatezu vermeiden, dass das ElseProgramm häufiger als nötig ausgeführt wird. Andernfalls verwenden (ReferenceDate>=Schedule(i, 1)). (Wenn der Test 50/50 ist, besteht kein Optimierungsbedarf)
brettdj
Möglicherweise wird es mit zahlreichen verschachtelten ifs etwas chaotisch ... wenn Sie beispielsweise einige Application.Match-Ergebnisse in jeder Iteration überprüfen müssen, um keine Übereinstimmung zu finden, bevor Sie die Ergebnisse verwenden. Aber so sei es, es gibt schlimmere Dinge im Leben!
JeopardyTempest
182

VBA verfügt nicht über ein Continueoder ein anderes gleichwertiges Schlüsselwort, um sofort zur nächsten Schleifeniteration zu springen. Ich würde eine vernünftige Verwendung Gotoals Problemumgehung vorschlagen , insbesondere wenn dies nur ein erfundenes Beispiel ist und Ihr realer Code komplizierter ist:

For i = LBound(Schedule, 1) To UBound(Schedule, 1)
    If (Schedule(i, 1) < ReferenceDate) Then
        PrevCouponIndex = i
        Goto NextIteration
    End If
    DF = Application.Run("SomeFunction"....)
    PV = PV + (DF * Coupon / CouponFrequency)
    '....'
    'a whole bunch of other code you are not showing us'
    '....'
    NextIteration:
Next

Wenn das wirklich Ihr ganzer Code ist, ist @Brian absolut korrekt. Fügen Sie einfach eine ElseKlausel in Ihre IfErklärung ein und fertig.

mwolfe02
quelle
18
Danke, das ist ein guter Tipp für das GoTo (VBA - strahlt Sie zurück bis 1964)
Richard H
3
@ George: GoTo kann missbraucht werden (weshalb ich meine Aussage qualifiziert habe; siehe vernünftig ), aber es ist nicht von Natur aus böse. Im Ernst, es ist unmöglich , eine robuste VBA ohne die Goto-Anweisung zu schreiben, nur weil Sie sie für die Fehlerbehandlung benötigen (dh On Error Goto).
mwolfe02
3
@ George: Was ich hier empfehle, ist eine Problemumgehung für eine weitere Einschränkung der Sprache (keine ContinueAussage). Man kann argumentieren, dass die Verwendung Continuein anderen Sprachen vermieden werden sollte und daher auch hier vermieden werden sollte. In gewisser Weise macht der Link, den Sie gepostet haben, meinen Standpunkt. Der Link führt zur GoToAnweisung in VB.Net. VB.Net verfügt sowohl über strukturierte Fehlerbehandlung als auch über Continue For/ Continue DoAnweisungen. GoToIn VB.Net ist dies wirklich nicht erforderlich . Ich vermute, dass es weitgehend beibehalten wurde, um die einfachere Konvertierung des vorhandenen VBA / VB6-Codes zu unterstützen.
mwolfe02
4
@ George GoTohat den Vorteil, dass die Verschachtelung reduziert wird. Das Überspringen einer Schleifeniteration ohne Hinzufügen einer Einrückungsstufe ist IMO eine der wenigen legitimen Verwendungen GoToin VBA / VB6. Vor allem, wenn Sie den Körper der Schleife in eine eigene Prozedur extrahieren .
Mathieu Guindon
4
@ George Ich habe Nesting gesehen, das nicht den Code bricht , sondern das Gehirn ruiniert ;)
Mathieu Guindon
35

Sie können eine Art continuevon verwenden, indem Sie ein verschachteltes verwenden Do ... Loop While False:

'This sample will output 1 and 3 only

Dim i As Integer

For i = 1 To 3: Do

    If i = 2 Then Exit Do 'Exit Do is the Continue

    Debug.Print i

Loop While False: Next i
Unbehandelte Ausnahme
quelle
1
interessant .. besser als mit goto!
Ozmike
Das ist großartig
Kubie
1
Dies sollte die Antwort sein
Stian Ulriksen
Sehr elegant und nett
Alexis Sánchez Tello
5
Klug! Ich würde es hassen, der Typ zu sein, der das ohne Kommentare findet. lol
Caltor
14

Continue For ist in VBA oder VB6 nicht gültig.

Von dieser MSDN-Seite scheint es in VS 2005/Net 2 in VB.Net eingeführt worden zu sein.

Wie die anderen gesagt haben, gibt es keine andere Option als die Verwendung Gotooder eine Else.

Jon Egerton
quelle
2

Hallo, ich bin auch mit diesem Problem konfrontiert und löse es mit dem folgenden Beispielcode

For j = 1 To MyTemplte.Sheets.Count

       If MyTemplte.Sheets(j).Visible = 0 Then
           GoTo DoNothing        
       End If 


'process for this for loop
DoNothing:

Next j 
Singaravelan
quelle
Ich bin mir nicht sicher, warum dies abgelehnt wurde und die nächste Antwort über 100 Stimmen hat, und sie sind die gleiche Antwort!
Rryanp
4
Wahrscheinlich, weil diese Antwort 5 Jahre nach dieser Antwort geschrieben wurde und genau das gleiche Konzept ist. Warum sollte dies Upvotes erhalten?
Tyler StandishMan
-2

Versuchen Sie vielleicht, alles am Ende zu setzen, wenn und verwenden Sie ein anderes, um den Code zu überspringen. Dadurch wird es so, dass Sie das GoTo nicht verwenden können.

                        If 6 - ((Int_height(Int_Column - 1) - 1) + Int_direction(e, 1)) = 7 Or (Int_Column - 1) + Int_direction(e, 0) = -1 Or (Int_Column - 1) + Int_direction(e, 0) = 7 Then
                Else
                    If Grid((Int_Column - 1) + Int_direction(e, 0), 6 - ((Int_height(Int_Column - 1) - 1) + Int_direction(e, 1))) = "_" Then
                        Console.ReadLine()
                    End If
                End If
richo7
quelle