VBA - cara melewatkan iterasi for loop secara kondisional


101

Saya memiliki loop for atas sebuah array. Yang ingin saya lakukan adalah menguji kondisi tertentu dalam loop dan lompat ke iterasi berikutnya jika benar:

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

Saya tahu saya bisa melakukan:

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

tetapi saya ingin dapat merekam nilai terakhir i di variabel PrevCouponIndex.

Ada ide?

Terima kasih


3
Anda berkata: "Saya Tahu Saya bisa melakukan: If (Schedule(i, 1) < ReferenceDate) Then Continue For" Apakah Anda yakin tentang itu? Continuebukan kata kunci VBA.
mwolfe02

@ mwolfe02 - tidak tidak yakin, tetapi melihat contoh di suatu tempat (cpearson?)
Richard H

mungkin contoh VB.NET
Anonymous Type

Jawaban:


31

Tidak bisakah kamu melakukan sesuatu yang sederhana seperti ini?

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
Memang, itulah yang telah saya lakukan :) Tapi tetap saja itu mengganggu saya, saya harus membungkus barang-barang di bagian Lain. Terima kasih
Richard H

4
+1 @RichardH Anda harus menggunakan IFuntuk tes jadi ini tidak terlalu mahal. Anda harus meskipun memastikan bahwa hasil yang paling umum adalah bahwa Schedule(i, 1)kurang dari ReferenceDateuntuk menghindari mengeksekusi Elselebih sering dari yang diperlukan. Jika tidak, gunakan (ReferenceDate>=Schedule(i, 1)). (jika pengujiannya 50/50 maka tidak perlu pengoptimalan)
brettdj

Mungkin akan sedikit berantakan dengan banyak jika bersarang ... jika misalnya Anda perlu memeriksa beberapa Application. Cocokkan hasil dalam setiap iterasi karena tidak menemukan yang cocok sebelum menggunakan hasil. Tapi biarlah, ada hal-hal yang lebih buruk dalam hidup!
JeopardyTempest

183

VBA tidak memiliki Continueatau kata kunci lain yang setara untuk segera melompat ke pengulangan berikutnya. Saya akan menyarankan penggunaan yang bijaksana Gotosebagai solusi, terutama jika ini hanya contoh yang dibuat-buat dan kode asli Anda lebih rumit:

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

Namun, jika itu benar-benar semua kode Anda, @Brian benar sekali. Letakkan saja Elseklausa dalam Ifpernyataan Anda dan selesaikan.


18
Terima kasih, itu tip yang bagus untuk GoTo (VBA - memancarkan Anda kembali ke tahun 1964)
Richard H

3
@ George: GoTo dapat disalahgunakan (itulah sebabnya saya memenuhi syarat pernyataan saya; lihat bijaksana ), tetapi itu tidak pada dasarnya jahat. Serius, tidak mungkin untuk menulis VBA yang kuat tanpa pernyataan Goto hanya karena Anda membutuhkannya untuk penanganan kesalahan (yaitu On Error Goto).
mwolfe02

3
@ George: Yang saya rekomendasikan di sini adalah solusi untuk batasan lain dari bahasa (tanpa Continuepernyataan). Seseorang dapat berargumen bahwa penggunaan Continuebahasa lain harus dihindari dan oleh karena itu harus dihindari di sini juga. Dalam beberapa hal, tautan yang Anda posting menjelaskan maksud saya. Tautannya ke GoTopernyataan di VB.Net. VB.Net memiliki penanganan kesalahan terstruktur dan Continue For/ Continue Dopernyataan. Benar-benar tidak perlu GoTodi VB.Net; Saya menduga itu dibiarkan sebagian besar untuk mendukung konversi yang lebih mudah dari kode VBA / VB6 yang ada.
mwolfe02

4
@George GoTomemiliki keuntungan mengurangi bersarang. Melewati iterasi loop tanpa menambahkan level indentasi adalah, IMO, salah satu dari sedikit penggunaan yang sah GoTodi VBA / VB6. Terutama jika Anda mengekstrak badan loop ke dalam prosedurnya sendiri .
Mathieu Guindon

4
@ George Saya telah melihat bersarang yang tidak memecahkan kode , tetapi merusak otak seseorang ;)
Mathieu Guindon

35

Anda bisa menggunakan semacam continuedengan menggunakan nested 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
menarik .. lebih baik daripada menggunakan goto!
ozmike

Ini luar biasa
Kubie

1
Ini harus menjadi jawabannya
Stian Ulriksen

Sangat elegan dan menyenangkan
Alexis Sánchez Tello

5
Pintar! Saya akan benci menjadi orang yang datang tanpa komentar sekalipun. lol
Caltor

14

Continue For tidak valid di VBA atau VB6.

Dari halaman MSDN ini sepertinya telah diperkenalkan ke VB.Net di VS 2005./Net 2.

Seperti yang dikatakan orang lain sebenarnya tidak ada pilihan selain menggunakan Gotoatau Else.


2

Hai, saya juga menghadapi masalah ini dan saya menyelesaikannya menggunakan kode contoh di bawah ini

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 

Tidak yakin mengapa ini ditolak dan jawaban berikutnya memiliki lebih dari 100 suara positif, dan mereka adalah jawaban yang sama!
rryanp

4
Mungkin karena jawaban ini ditulis 5 tahun setelah jawaban itu, dan merupakan konsep yang sama persis. Mengapa ini harus menerima suara positif?
Tyler StandishMan

-2

Mungkin mencoba meletakkan semuanya di akhir jika dan menggunakan yang lain untuk melewati kode ini akan membuatnya sehingga Anda tidak dapat menggunakan GoTo.

                        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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.