VBA - cách bỏ qua lặp lại vòng lặp for có điều kiện


101

Tôi có một vòng lặp for trên một mảng. Những gì tôi muốn làm là kiểm tra một điều kiện nhất định trong vòng lặp và chuyển sang lần lặp tiếp theo nếu đúng:

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

Tôi biết tôi có thể làm:

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

nhưng tôi muốn có thể ghi lại giá trị cuối cùng của i trong biến PrevCouponIndex.

Bất kỳ ý tưởng?

Cảm ơn


3
Bạn nói: "I Know I can do: If (Schedule(i, 1) < ReferenceDate) Then Continue For" Bạn có chắc về điều đó không? Continuekhông phải là một từ khóa VBA.
mwolfe02

@ mwolfe02 - (? cpearson) không không chắc chắn, nhưng cưa trong các ví dụ ở đâu đó
Richard H

có thể là một ví dụ VB.NET
Anonymous Loại

Câu trả lời:


31

Bạn không thể chỉ làm một cái gì đó đơn giản như thế này?

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
Thật vậy, đó là chính xác những gì tôi đã làm :) Nhưng vẫn có lỗi với tôi, tôi phải gói những thứ trong mảnh khác. Cảm ơn
Richard H

4
+1 @RichardH tốt, bạn phải sử dụng một IFcho bài kiểm tra để đây không phải là bộ mã đắt tiền. Mặc dù vậy, bạn nên đảm bảo rằng kết quả phổ biến nhất Schedule(i, 1)là ít hơn ReferenceDateđể tránh thực hiện Elsethường xuyên hơn mức cần thiết. Nếu không, hãy sử dụng (ReferenceDate>=Schedule(i, 1)). (nếu thử nghiệm là 50/50 thì không cần để tối ưu hóa)
brettdj

Chỉ có thể hơi lộn xộn với vô số if lồng nhau ... nếu ví dụ, bạn cần kiểm tra khá nhiều kết quả Application.Match trong mỗi lần lặp lại vì không tìm thấy kết quả phù hợp trước khi sử dụng kết quả. Nhưng có thể như vậy, có những điều tồi tệ hơn trong cuộc sống!
JeopardyTempest

183

VBA không có một Continuehoặc bất kỳ từ khóa tương đương nào khác để chuyển ngay đến lần lặp vòng lặp tiếp theo. Tôi sẽ đề xuất sử dụng một cách hợp lý Gotonhư một giải pháp thay thế, đặc biệt nếu đây chỉ là một ví dụ có sẵn và mã thực của bạn phức tạp hơn:

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

Tuy nhiên, nếu đó thực sự là tất cả mã của bạn, thì @Brian hoàn toàn chính xác. Chỉ cần đặt một Elsemệnh đề trong Iftuyên bố của bạn và được thực hiện với nó.


18
Cảm ơn, đó là một mẹo tốt tái GoTo (VBA - rạng rỡ bạn trở lại 1964)
Richard H

3
@George: GoTo có thể bị lạm dụng (đó là lý do tại sao tôi đủ điều kiện cho tuyên bố của mình; xem đúng đắn ), nhưng nó vốn dĩ không phải là xấu. Mặc dù vậy, nghiêm túc mà nói, không thể viết VBA mạnh mẽ mà không có câu lệnh Goto đơn giản vì bạn cần nó để xử lý lỗi (ví dụ On Error Goto:).
mwolfe02

3
@George: Những gì tôi đề xuất ở đây là một giải pháp thay thế cho một hạn chế khác của ngôn ngữ (không có Continuetuyên bố). Người ta có thể lập luận rằng Continuenên tránh sử dụng các ngôn ngữ khác và do đó cũng nên tránh ở đây. Theo một số cách, liên kết bạn đã đăng làm cho quan điểm của tôi. Liên kết đến GoTocâu lệnh trong VB.Net. VB.Net có cả xử lý lỗi cấu trúc và câu lệnh Continue For/ Continue Do. Thực sự không cần GoTotrong VB.Net; Tôi nghi ngờ rằng nó được giữ nguyên phần lớn để hỗ trợ việc chuyển đổi mã VBA / VB6 hiện có dễ dàng hơn.
mwolfe02

4
@George GoTocó lợi ích là giảm sự làm tổ. Bỏ qua lặp lại vòng lặp mà không thêm mức thụt lề là IMO, một trong số ít cách sử dụng hợp pháp GoTotrong VBA / VB6. Đặc biệt là nếu bạn trích xuất phần thân của vòng lặp thành thủ tục của riêng nó .
Mathieu Guindon

4
@George Tôi đã thấy lồng ghép không phá , nhưng làm hỏng não của một người ;)
Mathieu Guindon

35

Bạn có thể sử dụng một loại continuebằng cách sử dụng lồng nhau 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
thú vị .. tốt hơn là sử dụng goto!
ozmike

Điều này thật tuyệt vời
Kubie

1
Điều này sẽ là câu trả lời
Stian Ulriksen

Rất thanh lịch và tốt đẹp
Alexis Sánchez Tello

5
Tài giỏi! Mặc dù vậy, tôi rất ghét phải là người mà không có bình luận gì. lol
Caltor

14

Continue For không hợp lệ trong VBA hoặc VB6.

Từ trang MSDN này, có vẻ như nó đã được đưa vào VB.Net trong VS 2005./Net 2.

Như những người khác đã nói không thực sự có một lựa chọn nào khác ngoài việc sử dụng Gotohoặc một Else.


2

Xin chào, tôi cũng đang gặp phải vấn đề này và tôi giải quyết vấn đề này bằng cách sử dụng mã ví dụ bên dưới

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 

Không chắc tại sao câu trả lời này lại bị bỏ phiếu thấp và câu trả lời tiếp theo có hơn 100 phiếu bầu trở lên, và chúng là câu trả lời giống nhau!
rryanp 12/10/16

4
Có lẽ bởi vì câu trả lời này đã được viết 5 năm sau câu trả lời đó, và là cùng một khái niệm. Tại sao điều này nên nhận được sự ủng hộ?
Tyler StandishMan

-2

Có thể hãy thử đặt tất cả vào cuối cùng nếu và sử dụng một mã khác để bỏ qua mã, điều này sẽ khiến bạn không thể sử dụng 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.