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?)
Річард Н

можливо, це був приклад VB.NET
Анонімний тип

Відповіді:


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
Дійсно, це саме те, що я зробив :) Але все одно мене клопочуть, я мушу загортати речі в інший шматок. Спасибі
Річард Н

4
+1 @ RichardH добре, що ви повинні використовувати IFтест для тесту, так що це не такий дорогий код. Хоча вам слід переконатися, що найчастішим результатом Schedule(i, 1)є менше, ніж ReferenceDateуникати виконання Elseчастіше, ніж потрібно. В іншому випадку використовуйте (ReferenceDate>=Schedule(i, 1)). (якщо тест 50/50, то оптимізація не потребує)
brettdj

Просто можна трохи заплутатися з численними вкладеними ifs ... якщо, наприклад, вам потрібно перевірити досить багато Application.Match результатів у межах кожної ітерації, щоб не знайти відповідності перед використанням результатів. Але так і буде, в житті є гірші речі!
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 року)
Річард Н

3
@George: GoTo можна зловживати (саме тому я кваліфікував своє твердження; див. Розсудливий ), але це не властиво зло. Якщо серйозно, то неможливо написати надійний VBA без оператора Goto просто тому, що він потрібен для обробки помилок (тобто On Error Goto).
mwolfe02

3
@George: Що я тут рекомендую, це рішення для іншого обмеження мови (без Continueтвердження). Можна стверджувати, що вживання Continueінших мов слід уникати, а отже, і тут слід уникати. У чомусь, посилання, яке ви опублікували, робить мою думку. Посилання знаходиться на GoToзаяву у VB.Net. VB.Net має структуровану обробку помилок та Continue For/ Continue Doзаяви. В GoToVB.Net справді немає потреби ; Я підозрюю, що це було значною мірою підтримано більш легке перетворення існуючого коду VBA / VB6.
mwolfe02

4
@George GoToмає перевагу скорочення гніздування. Пропуск ітерації циклу без додавання рівня відступу - IMO - одне з небагатьох законних застосувань GoToу VBA / VB6. Особливо, якщо ви витягуєте тіло петлі в свою процедуру .
Матьє Гіндон

4
@George Я бачив гніздування, яке не порушує код , але руйнує мозок ;)
Матьє Гіндон

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!
озміке

Це приголомшливо
Кубі

1
Це має бути відповідь
Стіан Ульріксен

Дуже елегантно і приємно
Alexis Sánchez Tello

5
Розумний! Мені б не хотілося бути тим хлопцем, який натрапляє на це без коментарів, хоча. lol
Caltor

14

Continue For недійсний у VBA або VB6.

З цієї сторінки MSDN здається, що вона була внесена до VB.Net у VS 2005./Net 2.

Як говорили інші, немає дійсно іншого варіанту, ніж використовувати Gotoабо an Else.


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.