Перейти к содержимому
Наше приложение «Дешевые авиабилеты» в AppGallery >>

VBA Excel. Выход из вложенных циклов

    Досрочный выход из вложенных циклов в процедурах VBA Excel, когда стандартных конструкций «Exit For» и «Exit Do» не достаточно.

    Когда требуется выход из всех циклов?

    При разработке макросов и пользовательских функций в VBA Excel часто возникает необходимость прервать выполнение вложенных циклов досрочно — например, при нахождении искомого значения или при возникновении ошибки. Стандартная конструкция Exit For или Exit Do позволяет выйти только из текущего внутреннего цикла, но не из всех уровней вложенности.

    Представьте, что вы перебираете двумерный массив или таблицу, и как только находите нужное значение, дальнейший поиск теряет смысл. Если циклы вложены (например, строки и столбцы), то Exit For внутри внутреннего цикла прервёт только его, а внешний продолжит работу. Чтобы остановить все циклы, нужно использовать один из описанных ниже подходов, кроме первого, где применён, в качестве примера, Exit For для выхода только из одного внутреннего цикла.

    Использование Exit For для внутреннего цикла

    Базовый механизм, который обеспечивает выход только из одного внутреннего цикла с помощью конструкции Exit For:

    Как видите, после Exit For управление передаётся на строку Next i и внешний цикл продолжается. Это не то, что нам нужно, если мы хотим полностью прекратить поиск.

    Но в данном примере использование выхода только из внутреннего цикла оправдано — были найдены и вторые значения i и j, произведение которых равно 50:

    Найдено: i=5, j=10
    Найдено: i=10, j=5

    Использование флага (булевой переменной)

    Самый простой и читаемый способ выхода сразу из нескольких вложенных циклов — объявить переменную-флаг, которая будет сигнализировать о необходимости выхода. Во внутреннем цикле, при выполнении условия, устанавливаем флаг в True, затем проверяем его после выхода из внутреннего цикла и, при необходимости, выходим из внешнего.

    Результат работы кода:

    Найдено: i=5, j=10
    Поиск завершён досрочно.

    Плюсы: код легко читается, не требует GoTo или сложных конструкций.
    Минусы: нужно добавлять проверку после каждого внутреннего цикла.

    Использование GoTo для безусловного перехода

    Оператор GoTo позволяет передать управление на метку вне всех циклов. Это один из самых прямых способов.

    Результат работы кода:

    Найдено: i=5, j=10
    Циклы прерваны.

    Плюсы: кратко и просто, работает для любого уровня вложенности.
    Минусы: использование GoTo считается плохим тоном в структурированном программировании, может запутывать логику при большом количестве меток. В VBA это приемлемо, но злоупотреблять не стоит.

    Выход с помощью Exit Sub или Exit Function

    Если вложенные циклы находятся внутри отдельной подпрограммы или функции, и после нахождения условия дальнейший код не требуется, можно просто выйти из всей процедуры.

    Результат работы кода:

    Найдено: i=5, j=10

    Как видим, сообщение перед End Sub не выведено — произошёл выход из процедуры.

    Плюсы: очень просто и эффективно.
    Минусы: метод подходит только если после циклов не нужно выполнять никакой код (или его можно перенести в другое место).

    Комбинированный подход с вложенными проверками

    Иногда можно перестроить логику так, чтобы внешний цикл проверял условие на каждой итерации. Например, использовать цикл Do While с условием.

    Результат работы кода:

    Найдено: i=5, j=10

    Здесь условие продолжения каждого цикла включает проверку флага, что автоматически останавливает все уровни. Это достаточно элегантный способ, но требующий использование циклов в стиле Do While.

    Пример реального использования

    Мне впервые понадобился выход из вложенных циклов при сравнении 2 больших таблиц Excel.

    Таблица 1 — список населённых пунктов разных стран мира (58967 строк):
    Список населённых пунктов разных стран мира

    Таблица 2 — список населённых пунктов стран СНГ с кодом страны (7027 строк):
    Список населённых пунктов стран СНГ

    «Таблица 1» расположена на листе «Список», обращение к нему — Me, так как код размещён в его модуле. «Таблица 2» расположена на листе «Лист2».

    Необходимо произвести следующие действия:

    1. Пройтись циклом 1 уровня (внешним, охватывающим) по первому столбцу «Таблицы 1» (наименования населённых пунктов).
    2. Пройтись циклом 2 уровня (вложенным) по третьему столбцу «Таблицы 2» (Column4).
    3. Пройтись циклом 3 уровня вложенности по элементам списка каждой ячейки, выбранной циклом второго уровня, чтобы найти совпадение наименования из первой таблицы с наименованием в списке из этой ячейки.
    4. Из строки, где найдено совпадение наименований, скопировать наименование, транслитерацию и код страны на лист «Список новый».
    5. Выйти из вложенных циклов (внешний цикл продолжается до полного завершения).

    Для этих целей был использован следующий код:

    Несмотря на выход из вложенных циклов, код работал довольно долго. Ускорить его можно было бы, записывая данные не сразу на рабочий лист, а сначала в дополнительный массив.

    Резюме

    Выход из вложенных циклов в VBA Excel — частая задача, и для её решения есть несколько проверенных подходов. Самыми надёжными и читаемыми являются метод с булевым флагом и аккуратное использование GoTo.


    Содержание рубрики VBA Excel по тематическим разделам со ссылками на все статьи.