VBA - bir for döngüsü yinelemesini koşullu olarak atlama


101

Bir dizi üzerinde for döngüm var. Yapmak istediğim şey, döngüde belirli bir koşulu test etmek ve doğruysa sonraki yinelemeye geçmek:

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

Yapabileceğimi biliyorum:

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

ancak son i değerini PrevCouponIndex değişkenine kaydedebilmek istiyorum.

Herhangi bir fikir?

Teşekkürler


3
"Yapabileceğimi biliyorum If (Schedule(i, 1) < ReferenceDate) Then Continue For" dedin, bundan emin misin? Continuebir VBA anahtar sözcüğü değildir.
mwolfe02

@ mwolfe02 - emin değilim, ancak bir yerde örneklerde görüldü (cpearson?)
Richard H

bir VB.NET örneği olabilir
Anonim Tür

Yanıtlar:


31

Böyle basit bir şey yapamaz mısın?

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

4
Gerçekten de aynen bunu yaptım :) Ama yine de canımı sıkıyor Else parçasına bir şeyler sarmam gerekiyor. Teşekkürler
Richard H

4
+1 @RichardH IFtest için bir kullanmalısınız , yani kod olarak bu kadar pahalı değil. Yine de, en yaygın sonucun gereğinden daha sık uygulamaktan kaçınmaktan Schedule(i, 1)daha az olmasını ReferenceDatesağlamalısınız Else. Aksi takdirde kullanın (ReferenceDate>=Schedule(i, 1)). (test 50/50 ise optimizasyona gerek yoktur)
brettdj

Çok sayıda iç içe geçmiş ifs ile biraz dağınık olabilir ... örneğin, epeyce Application.Match sonuçlarını kullanmadan önce bir eşleşme bulamamak için her yinelemedeki sonuçları kontrol etmeniz gerekiyorsa. Ama öyle olsun, hayatta daha kötü şeyler var!
JeopardyTempest

183

VBA'nın bir Continuesonraki döngü yinelemesine hemen atlamak için bir veya başka bir eşdeğer anahtar sözcüğü yoktur. GotoÖzellikle bu sadece uydurma bir örnekse ve gerçek kodunuz daha karmaşıksa, geçici çözüm olarak mantıklı bir kullanım öneririm :

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

Eğer gerçekten kodunuzun tamamı buysa, @Brian kesinlikle doğrudur. Sadece ifadenize bir Elsecümle koyun Ifve onunla bitirin.


18
Teşekkürler, bu GoTo için iyi bir ipucu (VBA - sizi 1964'e geri gönderiyor)
Richard H

3
@George: GoTo suistimal edilebilir (bu yüzden beyanımı nitelendirdim; mantıklı görün ), ancak doğası gereği kötü değil. Cidden , Goto deyimi olmadan sağlam VBA yazmak imkansızdır çünkü hata işleme için buna ihtiyacınız vardır (yani, On Error Goto).
mwolfe02

3
@George: Burada önerdiğim şey, dilin başka bir sınırlaması için bir geçici çözüm (ifade yok Continue). ContinueBaşka dillerde kullanımından kaçınılması ve bu nedenle burada da kaçınılması gerektiği iddia edilebilir. Bazı açılardan, gönderdiğiniz bağlantı benim açımdan önemli. Bağlantı, GoToVB.Net'teki ifadeye bağlıdır. VB.Net hem yapılandırılmış hata işleme hem de Continue For/ Continue Doifadelerine sahiptir. GoToVB.Net'te gerçekten buna gerek yoktur ; Büyük ölçüde mevcut VBA / VB6 kodunun daha kolay dönüştürülmesini desteklemek için yerinde bırakıldığından şüpheleniyorum.
mwolfe02

4
@George GoTo, yuvalanmayı azaltma avantajına sahiptir. Bir döngü yinelemesini girinti düzeyi eklemeden atlamak, IMO, GoToVBA / VB6'daki birkaç yasal kullanımdan biridir . Özellikle de döngünün gövdesini kendi prosedürüne çıkarırsanız .
Mathieu Guindon

4
Ben kesilmez iç içe gördüğüm @George kodu , ancak kişinin virane beyin ;)
Mathieu Guindon

35

Bir tür continueiç içe geçmiş kullanarak kullanabilirsiniz 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

1
ilginç .. goto kullanmaktan daha iyi!
ozmike

Bu harika
Kubie

1
Cevap bu olmalı
Stian Ulriksen

Çok zarif ve hoş
Alexis Sánchez Tello

5
Zekice! Yine de buna yorum yapmadan rastlayan adam olmaktan nefret ederim. lol
Caltor

14

Continue For VBA veya VB6'da geçerli değildir.

Gönderen bu MSDN sayfasında o VS 2005./Net 2'de VB.Net girmiş gözüküyor.

Diğerlerinin söylediği gibi, kullanmaktan Gotoveya bir Else.


2

Merhaba ben de bu sorunla karşı karşıyayım ve bunu aşağıdaki örnek kodu kullanarak çözüyorum

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 

Bunun neden reddedildiğinden ve sonraki yanıtın 100'den fazla yukarı oy aldığından emin değilim ve bunlar aynı yanıt!
rryanp

4
Muhtemelen bu cevabın bu cevaptan 5 yıl sonra yazılmış olması ve tam olarak aynı kavram olmasıdır. Bu neden olumlu oy almalı?
Tyler StandishMan

-2

Belki de sonuna kadar koymayı deneyin, eğer kodu atlamak için başka bir tane kullanırsanız, bu onu GoTo'yu kullanamazsınız.

                        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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.