VBA. Организация циклов.
Операторы цикла используются для повторения выполнения действия или группы действий заданное количество раз. Количество повторений (итераций цикла) может быть предопределено или вычислено.
VBA поддерживает циклические конструкции двух видов:
- Циклы с фиксированным числом повторений (циклы со счетчиком ).
- Циклы с неопределенными числом повторений (циклы с условием ).
Для всех видов циклов используется понятие тело цикла , определяющее блок операторов, заключенных между начальным и конечным операторами цикла. Каждое повторение выполнения операторов тела цикла называется итерация .
Фиксированные циклы
VBA предоставляет две управляющие структуры для организации фиксированного цикла: For … Next (цикл со счетчиком) и For Each … Next (цикл с перечислением).
Оператор For … Next это типовой цикл со счетчиком, выполняющий заданное число итераций. Синтаксис оператора For … Next:
For <счетчик> = <начЗначение> То <конЗначение>
<блок операторов>
Next [<счетчик>]
Пример использования оператора For … Next.
Листинг 1. Оператор For … Next
‘ ЗАДАЧА: Составить программу, которая получает два числа от пользователя.
‘ Складывает все числа в диапазоне, заданном этими двумя числами, а затем
‘ отображает результирующую сумму.
Sub sample7()
Dim i As Integer ‘счетчик цикла
Dim sStart ‘начальное значение счетчика
Dim sEnd ‘конечное значение счетчика
Dim sSum As Long ‘результирующая сумма
sStart = InputBox(“Введите первое число:”)
sEnd = InputBox(“Введите второе число:”)
sSum = 0
For i = CInt(sStart) To CInt(sEnd)
sSum = sSum + i
Next i
MsgBox “Сумма чисел от ” & sStart & ” до ” & sEnd & ” равна: ” & sSum
End Sub
Оператор цикла For Each … Next относится к категории операторов объектного типа, т.е. применяется в первую очередь к коллекциям объектов , а также к массивам . Тело цикла выполняется фиксированное число раз, соответствующее числу элементов массива или коллекции. Формат оператора For Each … Next:
For Each <элемент> In <группа> <блок операторов> Next [<элемент>]
Циклы с условием (неопределенные циклы)
Циклы с условием используются в тех случаях, когда повторяющиеся действия нужно выполнять только при определенных условиях. Количество итераций не определено и в общем случае может быть равно нулю (в частности, для циклов с предусловием). VBA предлагает разработчикам несколько управляющих структур для организации циклов с условием:
- Четыре вида циклов Do..Loop, которые различаются типом проверяемого условия и временем выполнения этой проверки.
- Непрерываемый цикл While … Wend.
Цикл Do While … Loop – типичный цикл с предусловием . Условие проверяется до того, как выполняется тело цикла. Цикл продолжает свою работу, пока это <условие> выполняется (т.е. имеет значение True). Так как проверка выполняется в начале, то тело цикла может ни разу не выполниться. Формат цикла Do While … Loop:
Do While <условие>
<блок операторов>
Loop
Листинг 2. Цикл Do While … Loop
‘ ЗАДАЧА: Составить программу, которая предусматривает ввод пользователем
‘ произвольной последовательности чисел. Ввод должен быть прекращен
‘ только после того, как сумма введенных нечетных чисел превысит 100.
Sub sample8()
Dim OddSum As Integer ‘сумма нечетных чисел
Dim OddStr As String ‘строка с нечетными числами
Dim Num ‘для приема вводимых чисел
OddStr = “” ‘инициализация выходной строки
OddSum = 0 ‘инициализация суммы OddSum
Do While OddSum < 100 ‘начало цикла
Num = InputBox(“Введите число: “)
If (Num Mod 2) <> 0 Then ‘проверка на четность
OddSum = OddSum + Num ‘накопление суммы нечетных чисел
OddStr = OddStr & Num & ” ”
End If
Loop
‘вывод строки с нечетными числами
MsgBox prompt:=”Нечетные числа: ” & OddStr
End Sub
Оператор Do … Loop While предназначен для организации цикла с постусловием . Условие проверяется после того, как тело цикла, будет выполнено хотя бы один раз. Цикл продолжает свою работу, пока <условие> остается истинным. Формат цикла Do … Loop While:
Do <блок операторов> Loop While<условие>
Листинг 3. Цикл с постусловием
‘ ЗАДАЧА: Составить программу игры “Угадай число”. Программа должна случайным
‘ образом генерировать число в диапазоне от 1 до 1000, пользователь должен
‘ угадать это число. Программа на каждое вводимое число выводит подсказку
‘ “больше” или “меньше”.
Sub sample8()
Randomize Timer ‘ инициализация генератора случайных чисел
Dim msg As String ‘ строка сообщения
Dim SecretNumber As Long, UserNumber As Variant
Begin: SecretNumber = Round(Rnd * 1000) ‘ число, сгенерированное компьютером
UserNumber = Empty ‘ число, вводимое пользователем
Do ‘ игровой процесс
Select Case True
Case IsEmpty(UserNumber): msg = “Введите число”
Case UserNumber > SecretNumber: msg = “Слишком много!”
Case UserNumber < SecretNumber: msg = “Слишком мало!”
End Select
UserNumber = InputBox(prompt:=msg, Title:=”Угадай число”)
Loop While UserNumber <> SecretNumber
‘ проверка
If MsgBox(“Играть еще? “, vbYesNo + vbQuestion, “Вы угадали!”) = vbYes Then
GoTo Begin
End If
End Sub
Циклы Do Until … Loop и Do … Loop Until являются инверсиями ранее рассмотренных циклов с условием. В общем случае они работают аналогично, за исключением того, что тело цикла выполняется при ложном условии (т.е. <условие>=False). Формат цикла Do Until … Loop:
Do Until <условие> <блок операторов> Loop
Формат цикла Do … Loop Until:
<блок операторов>
Loop Until<условие>
Практическое задание: Перепишите программы из листингов 10 и 11 с использованием инвертированных операторов цикла.
Цикл While … Wend также относится к циклам с условием. Данный оператор полностью соответствует структуре Do While … Loop. Формат цикла While … Wend:
While <условие>
<блок операторов>
Wend
Отличительной особенностью этого оператора является невозможность принудительного завершения (прерывания) тела цикла (оператор Exit Do не работает в цикле While … Wend).
Прерывание цикла
Для досрочного завершения итерации и выхода из цикла применяется оператор Exit. Этот оператор применим в любой циклической структуре, кроме While … Wend. Общий синтаксис использования Exit для прерывания цикла таков:
<начало_цикла>
[<блок операторов1>]
Exit (For | Do)
[<блок операторов2>]
<конец_цикла>
При выполнении оператора Exit цикл прерывается, и управление передается оператору, следующему за оператором <конец_цикла>. В теле цикла может присутствовать несколько операторов Exit.
Листинг 4. Принудительный выход из цикла
Sub sample9()
For i = 1 To 10000000
If i = 10 Then Exit For ‘ выход из цикла, когда счетчик достигнет 10
Next
В этом уроке будет рассмотрена работа с циклом For в VBA. Пример работы с циклом For, так же будет продемонстрирован пример создания формул в Excel с помощью макросов.
Цикл For работает по принципу счетчика. For применяется в тех случаях, когда необходимо повторить некоторые действия заранее известное кол-во раз. Например, цикл For часто используется при чтении массивов.
Цикл For
имеет следующий синтаксис:
For
счетчик
=
начало цикла
To
конец цикла
[Step
шаг
]
группа операторов, команд и т.д.
Exit For
Next
счетчик
- "счетчик" - переменная, которая изменяется на указанный "шаг". Если шаг не указан, то по умолчанию берется единица.
- "начало цикла" , "конец цикла" - числа или переменные указывающие нижний предел счетчика и верхний. Остановка цикла происходит тогда, когда "счетчик" > "конец цикла" (или, если цикл обратный, т.е. с шагом -1, то "счетчик" < "конец цикла").
- Exit For – команда принудительной остановки цикла. Применяется в тех случаях, когда произошло некоторое событие, после которого необходимо остановить выполнение команд в цикле, или для предотвращения возникновения ошибки.
Рассмотрим пару примеров использования цикла For . В дальнейшем, с этим циклом будем встречаться довольно часто.
Пример 1
Даны два столбца С и Е заполненные числами:
Необходимо сложить числа в столбце С с числами столбца Е следующим образом:
С2+Е21, С3+E20, ..., C21+E2. Результат вывести в столбец D в виде формулы т.е. содержание ячейки результата должно быть "=С2+Е21".
Код макроса выглядит следующим образом (куда прописывать код читаем ):
Sub
Цикл_For()
"константа указывающая предел цикла т.е. до какого значения циклу бежать
Const
n = 21
For
i = 2 To
n
" создаем строку формулу и сохраняем ее в ячейку
Cells(i, 4) = "=C" & CStr
(i) & "+E" & CStr
((n - i) + 2)
" продолжение когда выполняющегося в цикле
Next
i
" остальной код программы
End Sub
Разбираем написанный код:
- Const n = 21 - описание константы n со значением 21, т.е. число строк по которому необходимо пробежаться циклу For ;
- For i = 2 To n - i счетчик который будет изменяться на 1 с каждым проходом цикла. Счетчик начинается с 2 и заканчивается когда i>n;
- Cells(i, 4) - ячейка выделенного листа, i номер строки, 4 -номер столбца в который выводится результат. Обратите внимание, наш счетчик i указывает номер строки листа Excel;
- Next i - оператор закрытия цикла и перевода указателя к For. Все что находится между For и Next выполняется в цикле;
- CStr - функция преобразующая число в текст.
Ячейке мы присваиваем формулу созданную следующим образом "=C" & CStr
(i) & "+E" & CStr
((n - i) + 2). Знак & - "склеивание" символов, строк. В результате у нас получится формула "=Сn+E((n - i) + 2)" где n = 21, i - счетчик.
Страшно? Это только кажется:)
Все. После выполнения макроса мы получим следующий столбец (выделен), а в каждой ячейке формула:
Пример 2
Теперь рассмотрим цикл с указанным шагом. После расчета прошлого макроса мы получили три столбца, теперь нам необходимо из столбца E вычесть D, в столбец F вывести формулы вычитания. Код макроса следующий:
Sub
Цикл_For_с_шагом()
Const
n = 21
For
i = n To
2 Step
-1
Cells(i, 6) = "=E" & CStr
(i) & "-D" & CStr
(i)
Next
i
End Sub
В данном случае все тоже самое, только цикл теперь "бежит" не от 2, а от 21 до 2 с шагом (Step) -1.
Результат выполнения получим следующий:
Цикл For , в VBA, является не единственным циклом. В дальнейшем будут рассмотрены еще пара вариантов циклов, без которых не обойтись при написании макрокоманд в Excel.
Цикл - это группа операторов, которые многократно выполняются. Для организации циклов в VBA, т. е. многократного выполнения одного или нескольких операторов, можно использовать две основные группы: циклы с перечислением For...Next и циклы с условием Do... Loop. Существуют две разновидности For...Next (For-Next и For Each-Next) и два вида циклов Do...Loop (Do While...Loop и Do Until ...Loop), которые различаются типом проверяемого условия.
Цикл For-NextСамым распространенным циклом в VBA является цикл с перечислением "For-Next". Этому циклу необходимо задать границы (начальное и конечное значения счетчика) в пределах которых будет изменяться переменная цикла.
Оператор цикла имеет следующий синтаксис:
For
For
n = 1)
То
Конечное Значение (То
10)
Step
Приращение (Step
2)
Next
[счетчик]
Здесь переменная - это счетчик, значение переменной увеличивается или уменьшается с каждым повторением цикла. Если в конструкции цикла отсутствует Step, то приращение равно 1 (по умолчанию). Для досрочного выхода из оператора цикла, т.е. до достижения счетчиком конечного значения, в конструкцию цикла надо ввести оператор Exit For .
С учетом Exit For
оператор цикла имеет следующий синтаксис:
For
счетчик = Начальное Значение (например, Например, For
n = 1)
То
Конечное Значение (То
10)
Step
Приращение (Step
2)
[Инструкции] или [блок Операторов]
Exit For
Next
[счетчик]
Для обработки группы однородных объектов или массивов применяется следующая конструкция цикла:
For Each
Элемент In
Группа (имя группы однородных объектов)
[Инструкции] или [блок Операторов]
Exit For
Next
элемент
Оператор Do While…Loop выполняет циклы до тех пор, пока соблюдается какое-либо заданное условие. Необходимо отметить, что условие проверяется до того, как выполняется инструкция или группа операторов.
В этом случае синтаксис операторов цикла Do While...Loop имеет следующий вид:
Do While
условие (Например, x<20)
[Инструкции] или [блок Операторов]
Exit Do
Loop
Do
[Инструкции] или [блок Операторов]
Exit Do
Loop While
условие
Оператор Do Until…Loop выполняет циклы до тех пор, пока условие не соблюдается, а при соблюдении условия оператор выходит из цикла. Условие проверяется до того, как выполняется инструкция или группа операторов.
В этом случае синтаксис операторов цикла Do Until...Loop имеет следующий вид:
Do Until
условие (Например, x=20)
[Инструкции] или [блок Операторов]
Exit Do
Loop
Если надо проверять условие после того, как инструкции или блок операторов будут выполнены хотя бы один раз, то можно применить следующую конструкцию оператора цикла:
Do
[Инструкции] или [блок Операторов]
Exit Do
Loop Until
условие
Цикл – это алгоритмическая структура, при помощи которой реализуется многократное повторение блока операторов.
Оператор цикла со счетчиком (For … Next)
Инструкция For … Next позволяет циклически выполнить набор инструкций (операторов) заданное количество раз. Синтаксис инструкции:
For счетчик = нач_значение To конеч_значение
[инструкции ]
[инструкции ]
Next [счетчик ]
Параметр счетчик – это числовая переменная, автоматически изменяющая свое значение на величину шаг после каждого повтора цикла. Цикл выполняется до тех пор, пока счетчик £ конеч_значение при положительном значении параметра шаг или до тех пор, пока счетчик ³ конеч_значение при отрицательном значении параметра шаг . Таким образом, цикл не выполнится ни разу, если при положительном значении шага нач_значение больше, чем конеч_значение . Если параметр Step шаг опущен, то по умолчанию приращение переменной-счетчика полагается равным 1.
Оператор Exit For завершает выполнение цикла "досрочно" и передает управление оператору, следующему за оператором цикла. Exit For обычно располагают в условном операторе, например:
If условие Then Exit For
Примечание. По синтаксису оператора For параметр счетчик – арифметическая переменная любого типа, все же лучше использовать целый тип переменной, т. к. дробная часть значения переменной вещественного типа обычно имеет погрешность. Это связано со способом хранения чисел в компьютере.
Пример 1
Найти сумму первых 10 натуральных чисел: S = 1 + 2 + 3 + … + 10 . Фрагмент программы:
Dim I as Integer, S as Integer
S = 0 " Обнуляем значение переменной S
For i = 1 to 10 "
Начало цикла. Задаем начальное и конечное значения
"параметра цикла. Шаг цикла по умолчанию равен 1.
S = S + i "
Оператор присваивания выполняется при каждом
" выполнении цикла, в данном примере 10 раз
Next I " Конец цикла. Значение параметра цикла увеличивается на шаг.
В этом фрагменте программы цикл выполнится ровно 10 раз.
Пример 2
Вывести в 1-й столбец рабочего листа (начиная со2-й строки) значения х в диапазоне от 0 до 3,2 с шагом 0,4.
Public Sub Табуляция()
Dim x As Single, i As Integer
For x = 0 To 3.2 Step 0.4
Хотя длина интервала точно делится на шаг 0.4, результат на рабочем листе имеет вид:
Что же предпринять?
1. Можно слегка увеличить конечное значение, в данном примере вместо 3.2 написать 3.201.
2. Определить число повторений чикла и написать цикл по счетчику целого типа.
В данном случае программа примет вид:
Public Sub Табуляция1()
Dim x As Single, i As Integer, n As Integer
n = CInt((3.2 - 0) / 0.4)
For i = 0 To n Step 1
Cells(i + 2, 1) = x
Оператор цикла For Each … Next
Цикл For Each … Next позволяет повторить выполнение группы инструкций для каждого элемента массива или семейства. Данная инструкция имеет следующий синтаксис:
For Each элемент In группа
[инструкции ]
[инструкции ]
Next [элемент ]
Параметр элемент – это переменная, которая представляет элемент семейства или массива. Аргумент группа – имя массива или семейства. Инструкции выполняются только один раз для каждого члена группы. Использование инструкции удобно потому, что не требуется заранее знать, сколько элементов содержится в массиве или семействе. Переменная элемент должна иметь тип Variant.
Пример 1
Найти среднее арифметическое значение всех элементов выделенного диапазона
Public Function Среднее(Диапазон As Range) As Double
Dim Элемент As Variant
Dim Сумма As Double
Dim Количество As Integer
Количество = 0
For Each Элемент In Диапазон
Сумма = Сумма + Элемент
Количество = Количество + 1
Next Элемент
Среднее = Сумма / Количество
Применение. В выделенном диапазоне смежных ячеек должны находиться числа. Числа в пустых ячейках считаются равными 0. Текст в ячейке приведет к ошибке.
Перечисленные выше операторы If … End If, Select … Case, For … Next, For Each … Next представляют собой группу управляющих инструкций, которые изменяют порядок выполнения команд. Управляющие инструкции могут быть вложены друг в друга в любой последовательности.
Последнее обновление: 30.10.2015
Еще одним видом управляющих конструкций являются циклы. В VB.NET используется несколько видов циклов.
Цикл For...Next
В этом цикл выполняется определенное число раз, причем это число задается счетчиком:
For i As Integer = 1 To 9 Console.WriteLine("Квадрат числа {0} равен {1}", i, i * i) Next
Здесь переменная i выполняет роль счетчика. После слова To мы помещаем максимальное значение счетчика. При каждом цикле значение счетчика увеличивается на единицу. И это значение сравнивается со значением после To . Если эти два значения равны, то цикла прекращает свою работу.
При работе с циклами мы можем увеличивать значение счетчика при каждом проходе не только на единицу, но и вообще на любое число. Для этого нужно либо использовать ключевое слово Step и после него указать шаг цикла, на который будет увеличиваться значение счетчика, либо можно увеличивать счетчик непосредственно в цикле:
For i As Integer = 1 To -9 Step -1 For j As Integer = 1 To 9 Console.WriteLine("Произведение чисел i и j равно {0}", i * j) j += 1 Next Next
Обратите внимание, что в качестве шага в первом цикле выбрано отрицательное значение и значение счетчика с каждым проходом уменьшается на единицу. Во внутреннем цикле счетчик j при каждом проходе увеличивается на 2, так как он по умолчанию увеличивается на единицу, и еще мы явным образом увеличиваем его в цикле на единицу. В итоге внутренний цикл отрабатывает пять раз, а внешний девять, то есть фактически получается 45 циклов.
Цикл For Each...Next
Цикл For Each осуществляет перебор элементов в определенной группе, например, в массиве или в коллекции. Предположим у нас есть некоторый массив типа Integer и нам надо инициализировать этот массив случайными значениями и затем вывести все его элементы на экран:
"Создаем массив из пяти чисел Dim nums(4) As Integer Dim r As New Random() "инициализируем массив For i As Integer = 0 To nums.Length - 1 nums(i) = r.Next(100) Next "Выводим элементы массива For Each i As Integer In nums Console.Write("{0} ", i) Next
В выражении For Each мы сначала указываем переменную, которая будет принимать значения элементов массива. А после ключевого слова In указываем группу, в которой надо перебрать все элементы.
Цикл While
В цикл While выполняется до тех пор, пока соблюдается определенное условие, указанное после слова While:
Dim j As Integer = 10 While j > 0 Console.WriteLine(j) j -= 1 End While
Цикл Do
Цикл Do, также как и цикл While, выполняется, пока соблюдается определенное условие. Однако он имеет разные формы. Так, в следующем примере сначала проверяется условие, а затем выполняется блок кода, определенный в цикле:
Dim j As Integer = 10 Do While j > 0 Console.WriteLine(j) j -= 1 Loop
В данном случае цикл выполняется, пока значение j больше нуля. Но есть еще одна запись, где вместо слова While используется слово Until , а цикл выполняется пока не соблюдено определенное условие, то есть пока значение j не станет меньше нуля:
Dim j As Integer = 10 Do Until j < 0 Console.WriteLine(j) j -= 1 Loop
Если изначально условие, заданное в цикле, неверно, то цикл не будет работать. Но мы можем определить проверку в конце цикла, и таким образом, наш цикл как минимум один раз отработает:
Dim j As Integer = -1 Do Console.WriteLine(j) j -= 1 Loop Until j < 0 "либо Do Console.WriteLine(j) j -= 1 Loop While j > 0
Операторы Continue и Exit
Нередко возникает необходимость не дожидаться окончания цикла, а сразу же выйти из цикла, в случае соблюдения определенного условия. Для этого используют оператор Exit , после которого указывают тип цикла, из которого осуществляется выход, например, Exit Do (Exit While) :
Dim r As New Random() Dim num As Integer = r.Next(100) For i As Integer = 0 To 100 num -= 1 If num < 50 Then Exit For Next Console.WriteLine(num)
Существует и другая задача - осуществить выход не из цикла, а из текущего прохода или итерации и перейти к следующему. Для этого используют оператор Continue , после которого указывают тип цикла, из которого осуществляется выход, например, Continue While:
Dim r As New Random() Dim num As Integer = r.Next(100) For i As Integer = 0 To 10 num -= 7 If num < 50 AndAlso num > 25 Then Continue For End If Console.WriteLine(num) Next
В данном случае мы в каждом проходе цикла вычитаем из num число 7 и затем смотрим, не принадлежит ли число num интервалу от 25 до 50. И если принадлежит, переходим к новой итерации цикла, а если нет, то выводим его на экран.
Оптимизация