VBA - วิธีการข้ามการวนซ้ำแบบมีเงื่อนไข


101

ฉันมีสำหรับลูปเหนืออาร์เรย์ สิ่งที่ฉันต้องการทำคือทดสอบเงื่อนไขบางอย่างในลูปและข้ามไปยังการทำซ้ำถัดไปหากเป็นจริง:

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

ฉันรู้ว่าฉันทำได้:

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

แต่ฉันต้องการบันทึกค่าสุดท้ายของ i ในตัวแปร PrevCouponIndex

ความคิดใด ๆ ?

ขอบคุณ


3
คุณบอกว่า: "ฉันรู้ว่าฉันทำได้: If (Schedule(i, 1) < ReferenceDate) Then Continue For" คุณแน่ใจหรือไม่? Continueไม่ใช่คำหลัก VBA
mwolfe02

@ mwolfe02 - ไม่แน่ใจ แต่เห็นในตัวอย่างที่ไหนสักแห่ง (cpearson?)
Richard H

อาจเป็นตัวอย่าง VB.NET
Anonymous Type

คำตอบ:


31

ทำอะไรง่ายๆแบบนี้ไม่ได้เหรอ?

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
อันที่จริงคือสิ่งที่ฉันได้ทำไปแล้ว :) แต่ก็ยังทำให้ฉันมีข้อบกพร่องฉันต้องห่อของเป็นชิ้นอื่น ขอบคุณ
Richard H

4
+1 @RichardH ดีคุณต้องใช้IFสำหรับการทดสอบดังนั้นนี่ไม่ใช่รหัสที่แพงขนาดนั้น คุณควรตรวจสอบให้แน่ใจว่าผลลัพธ์ที่พบบ่อยที่สุดนั้นSchedule(i, 1)น้อยกว่าReferenceDateเพื่อหลีกเลี่ยงการดำเนินการElseบ่อยเกินความจำเป็น (ReferenceDate>=Schedule(i, 1))มิฉะนั้นใช้ (ถ้าการทดสอบเป็น 50/50 ก็ไม่จำเป็นต้องปรับให้เหมาะสม)
brettdj

อาจจะยุ่งเล็กน้อยกับ ifs ที่ซ้อนกันมากมาย ... ตัวอย่างเช่นคุณต้องการตรวจสอบแอปพลิเคชันค่อนข้างน้อยจับคู่ผลลัพธ์ภายในการวนซ้ำแต่ละครั้งเพื่อไม่ให้พบการจับคู่ก่อนที่จะใช้ผลลัพธ์ แต่ไม่ว่าจะเป็นเรื่องที่เลวร้ายกว่าในชีวิต!
JeopardyTempest

183

VBA ไม่มีContinueคีย์เวิร์ดอื่นที่เทียบเท่าเพื่อข้ามไปยังการวนซ้ำรอบถัดไปทันที ฉันขอแนะนำให้ใช้Gotoเป็นวิธีแก้ปัญหาอย่างรอบคอบโดยเฉพาะอย่างยิ่งหากนี่เป็นเพียงตัวอย่างที่สร้างขึ้นและรหัสจริงของคุณมีความซับซ้อนมากขึ้น:

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

ถ้านั่นเป็นรหัสทั้งหมดของคุณจริงๆ @Brian ถูกต้องอย่างแน่นอน เพียงแค่ใส่ElseประโยคในIfคำสั่งของคุณและดำเนินการกับมัน


18
ขอบคุณนั่นเป็นเคล็ดลับที่ดีสำหรับ GoTo (VBA - ทำให้คุณนึกถึงปี 1964)
Richard H

3
@ จอร์จ: GoTo สามารถถูกทำร้ายได้ (ซึ่งเป็นเหตุผลว่าทำไมฉันถึงมีคุณสมบัติตามคำพูดของฉันดูมีวิจารณญาณ ) แต่มันไม่ได้ชั่วร้ายโดยเนื้อแท้ แม้ว่าอย่างจริงจังมันเป็นไปไม่ได้ที่จะเขียน VBA ที่มีประสิทธิภาพโดยไม่มีคำสั่ง Goto เพียงเพราะคุณต้องการมันเพื่อจัดการข้อผิดพลาด (เช่นOn Error Goto)
mwolfe02

3
@ George: สิ่งที่ฉันแนะนำต่อไปนี้เป็นวิธีแก้ปัญหาสำหรับข้อ จำกัด อื่นของภาษา (ไม่มีContinueคำชี้แจง) เราสามารถโต้แย้งได้ว่าContinueควรหลีกเลี่ยงการใช้ภาษาอื่นดังนั้นจึงควรหลีกเลี่ยงที่นี่เช่นกัน ในบางวิธีลิงก์ที่คุณโพสต์ทำให้ฉันเข้าใจ ลิงค์ไปที่GoToคำสั่งใน VB.Net VB.Net มีทั้งการจัดการข้อผิดพลาดที่มีโครงสร้างและContinue For/ Continue Doคำสั่ง ไม่มีความจำเป็นGoToใน VB.Net อย่างแท้จริง ฉันสงสัยว่ามันถูกทิ้งไว้เพื่อรองรับการแปลงรหัส VBA / VB6 ที่มีอยู่ได้ง่ายขึ้น
mwolfe02

4
@ จอร์จGoToมีประโยชน์ในการลดการสร้างรัง การข้ามการวนซ้ำแบบวนซ้ำโดยไม่ต้องเพิ่มระดับการเยื้องคือ IMO ซึ่งเป็นหนึ่งในไม่กี่ตัวที่ใช้GoToใน VBA / VB6 โดยเฉพาะอย่างยิ่งถ้าคุณดึงม้วนตัวเข้าสู่ขั้นตอนของตัวเอง
Mathieu Guindon

4
@ George ฉันเคยเห็นการทำรังที่ไม่ทำลายรหัสแต่ทำลายสมองของใครบางคน;)
Mathieu Guindon

35

คุณสามารถใช้ชนิดของมันcontinueโดยใช้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
น่าสนใจ.. ดีกว่าใช้ goto!
ozmike

ยอดเยี่ยมมาก
Kubie

1
นี่ควรเป็นคำตอบ
Stian Ulriksen

สง่างามและสวยงามมาก
Alexis Sánchez Tello

5
ฉลาด! ฉันเกลียดที่จะเป็นผู้ชายที่เจอแบบนั้นโดยไม่มีความคิดเห็นเลย lol
Caltor


2

สวัสดีฉันกำลังประสบปัญหานี้และฉันแก้ปัญหานี้โดยใช้โค้ดตัวอย่างด้านล่าง

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 

ไม่แน่ใจว่าทำไมถึงได้รับการโหวตต่ำลงและคำตอบถัดไปมีคะแนนโหวตมากกว่า 100 คะแนนและเป็นคำตอบเดียวกัน!
rryanp

4
อาจเป็นเพราะคำตอบนี้เขียนขึ้น 5 ปีหลังจากคำตอบนั้นและเป็นแนวคิดเดียวกัน เหตุใดจึงควรได้รับคะแนนโหวตเพิ่ม
Tyler StandishMan

-2

บางทีลองใส่มันทั้งหมดในตอนท้ายถ้าและใช้วิธีอื่นเพื่อข้ามรหัสสิ่งนี้จะทำให้คุณไม่สามารถใช้ 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.