2016-11-08 1 views
0

Я честно не знаю, почему компилятор VBA меня изматывает из-за этого GoTo Jump, соответственно Jump:.Excel VBA: прыжок внутри цикла for: «Next for For» - Что я делаю неправильно?

counter2 = 0 
    If (counter1 > 1) Then 
     For i = 0 To (MaxLastCell - 4) 
      If (IncompleteRows(i) = 1) Then 
       If ((counter2 > 1) And (counter2 < counter1)) Then 
        x = x + ", " + CLng(i) 
        counter2 = counter2 + 1 
        GoTo Jump 
       End If 
       If ((counter2 > 1) And (counter2 = counter1)) Then 
        x = x + " and " + CLng(i) 
        GoTo Outside 
       If (counter2 = 0) Then 
        x = CLng(i) 
        counter2 = 1 
       End If 
      End If 
Jump: 
     Next i 

Каждый раз, когда я пытаюсь запустить свой код, этот фрагмент кода представляет собой проблему. Компилятор отмечает Next в самом низу и сообщает мне, что есть "Next without For".

Но разве этот вид кодирования не должен работать? Я только что видел here. Странная вещь, однако, заключается в том, что компилятор там, похоже, не принуждал B H перемещать точку прыжка NextIteration: влево, но позволял ему оставаться на втором уровне отступа и, таким образом, в пределахfor -loop, as кажется. (Ли это, что даже имеет значения?)

+2

Измените структуру IF на ElseIF, как показано ниже. Затем вы можете удалить строку перехода goto и заменить goto Outside на 'Exit For'. –

ответ

1

попробовать это (пересмотр отмеченного в комментариях):

counter2 = 0 
    If (counter1 > 1) Then 
     For i = 0 To (MaxLastCell - 4) 
      If (IncompleteRows(i) = 1) Then 
       If ((counter2 > 1) And (counter2 < counter1)) Then 
        x = x + ", " + CLng(i) 
        counter2 = counter2 + 1 
        GoTo Jump 
       End If 
       If ((counter2 > 1) And (counter2 = counter1)) Then 
        x = x + " and " + CLng(i) 
        GoTo Outside 
       ElseIf (counter2 = 0) Then '<--*** changed from simple 'If' 
        x = CLng(i) 
        counter2 = 1 
       End If 
      End If 
Jump: 
     Next i 
    End If '<--*** added 

но вы должны избегать GOTOS

1

У вас есть какой-то хороший код спагетти там. GoTo - лишь плохая альтернатива правильному потоку управления.

Neal Stephenson thinks it's cute to name his labels 'dengo'

Один GoTo к "перейти к следующей итерации", это одно. Другой - GoTo Outside (где бы это ни было) - это что-то другое.

VBA (спецификация языка) не заботится о том, в какой колонке начинается метка линии; для всех, кого мы знаем, ответ, на который вы ссылались, был введен в поле ответа, а не в VBE. Когда VBE (IDE/editor) видит метку линии, она автоматически перемещает ее в столбец 1, так же как она автоматически вставляет пробелы между операторами и операндами и точно так же, как автоматически настраивает оболочку ключевых слов и идентификаторов по мере их ввода. Так что нет, это не имеет значения.

VBA синтаксис требует блоки должны быть закрыты: так же, как Sub DoSomething() процедуры сусла конца с End Sub и With блоком сусла конец с End With, в For блоке сусла конец с Next. Правильные отступы и небольшие процедуры обычно помогают получить это право.

Много других языков (C#, Java, C++ и т.д.) имеют сходные ограничения относительно того, что делает правильный блок кода (несогласованные { и } Брекеты ошибка компилятора на любом языке, который использует их AFAIK), так что не является VBA придирчивым или жаловаться без причины.

Это говорит о том, что трудно определить, является ли ваш код неправильным, потому что вы не включаете всю область процедуры, поэтому мы должны предположить, что после вашего фрагмента нет ничего другого, - и фрагмент, который вы опубликовали, отсутствует End Ifas user3598756 has noted:

If (counter1 > 1) Then 
    '...code... 
End If 

Итак, как идти о реструктуризации этого?

  • Предполагая, что метка Outside линии расположена непосредственно перед End Sub (или это End Function?), То вы можете заменить его Exit Sub (или Exit Function) и назвать его в день.
    • Если есть код, который необходимо запустить после цикла, но до конца области действия, Exit For выведет вас из цикла, удерживая вас внутри процедуры - следующая строка для запуска будет первым исполняемым оператором который следует за токеном Next.
  • Теперь возьмите условие, которое заставляет цикл пропускать итерацию и перефразировать тело цикла соответственно; использовать ElseIf, чтобы избежать оценки условий вам не нужно, и удалить все эти посторонние и запутанные скобки:

    If IncompleteRows(i) = 1 And counter2 > 1 And counter2 < counter1 Then 
        x = x + ", " + CLng(i) 
        counter2 = counter2 + 1 
    ElseIf counter2 > 1 And counter2 = counter1 Then 
        x = x + " and " + CLng(i) 
        Exit For ' assuming... 
    ElseIf counter2 = 0 Then 
        x = CLng(i) 
        counter2 = 1 
    End If 
    

    И это было бы все тело цикла. Конечно, его можно было бы улучшить; counter2 > 1 повторяется дважды, поэтому есть место для дальнейшей реструктуризации. Но уже, все GoTo исчезли.

Смежные вопросы