Цикл большего значения индекса к меньшему vba. Циклы VBA. Циклы могут быть вложенными в другие циклы

Операторы цикла

В VBA существуют два основных типа циклов – циклы со счетчиком (параметрические) и циклы с условием (итерационные).

Циклы со счетчиком используют в тех случаях, когда необходимо выполнить некоторые действия определенное число раз

Циклы с условием применяются тогда, когда некоторые действия в программе должны повторяться до тех пор, пока выполняется определенное условие.

Циклы с параметром For … Next

Структура цикла:

For Параметр_Цикла = Начальное_Значение To Конечное_Значение

[ Step Шаг]

Операторы

[ Exit For ]

Next [Параметр_Цикла]

где For – ключевое слово VBA (от), обозначающее начало цикла;

Параметр_цикла – переменная, определенная в качестве счетчика цикла;

Начальное_Значение – число, задающее начальное значение параметра цикла;

To – ключевое слово VBA (до), разделяющее

Начальное_значение и Конечное_Знаение;

Конечное_Значение – число, задающее значение параметра цикла,

При котором цикл завершается;

Step – ключевое слово VBA (шаг), используемое для

Задания шага цикла, необязательный аргумент;

Шаг – число, задающее шаг цикла, т.е. значение, на которое

Увеличивается (или уменьшается) значение параметра

Цикла на каждом шаге. Это число может быть

Отрицательным;

Exit For – оператор досрочного выхода из цикла (необязательный);

Next – ключевое слово VBA (следующий), обозначающее

Конец цикла.

Работа цикла:

Шаг 1 Сначала определяется параметр цикла, а также вычисляются и запоминаются начальное и конечное значения этой переменной.

Шаг 2 Параметру цикла присваивается начальное значение.

Шаг 3 Начальное значение параметра цикла сравнивается с конечным значением.

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

Шаг 4 Выполняется тело цикла.

Шаг 5 После выполнения тела цикла происходит присваивание параметру цикла следующего значения. Переход к шагу 3.

Примечание.

1. Если используется ключевое слово Step , то параметр цикла изменяется в соответствии с числом, указанным после этого слова. Если слово Step отсутствует, то значение шага равно единице.

Пример 1.

For I = 0 To 10 Step 2 (Значение I будет увеличиваться на 2)

2. Цикл For … Next может быть прерван досрочно при достижении какого либо условия. Для этого в нужном месте цикла нужно поместить оператор Exit For .

Пример 2.

Dim S As Integer

Dim j As Integer

S = 2

For j = 1 To 10

S = S + j

If S > 6 Then

Exit For (Выход из цикла, если значение S > 6)

End If

Next j

MsgBox (S)

Циклы с условием (итерационные)

Если какое-то действие (несколько действий) необходимо выполнить много раз, но заранее неизвестно сколько раз и это зависит от какого-то условия, то тогда следует воспользоваться циклом с предусловием или с постусловием.

В VBA есть два основных цикла DO … LOOP – с условием, вводимым ключевым словом While , и с условием, вводимым ключевым словом Until . Оба они могут быть с предусловием или с постусловием.

Синтаксис:

где Do – ключевое слово (делать);

While – ключевое слово (пока);

Until – ключевое слово (до тех пор пока);

Loop – ключевое слово, указывающее на окончание цикла;

<условие> – логическое выражение, истинность которого проверяется

В начале каждого выполнения тела цикла;

<тело_цикла> – произвольная последовательность операторов;

Конструкция Do … While читается: делать пока выполняется условие. В конструкции Do … While For

Конструкция Do … Until читается: делать до тех пор, пока не будет выполнено условие. В конструкции Do … Until для увеличения шага следует писать специальный оператор, т.к. в ней в отличие от конструкции For , не делается это автоматически.

Условие, записанное после ключевого слова Until , проверяется в конце каждой итерации (после выполнения тела цикла). Обратить внимание, что оно работает здесь не совсем так, как в цикле While . Если условие является истинным (True ), то выполнение цикла завершается. Если условие не выполняется (является ложным – False ), то вновь выполняется тело цикла.

Пример 1.

Постановка задачи. Вычислить сумму конечного ряда с помощью подпрограммы-процедуры.

Технология выполнения задания:

1. Исходные данные: i  Z

Результат: S  R .

2.Набрать в стандартном модуле проекта следующую пользовательскую процедуру, используя цикл с предусловием While :

Sub summa()

Dim S As Integer

Dim i As Integer

S = 0

i = 1

Do While i <= 10

S = S + i ^ 2

i = i + 1

Loop

MsgBox (S)

End Sub

3.Набрать в стандартном модуле проекта следующую пользовательскую процедуру, используя цикл с предусловием Until :

Sub summa()

Dim S As Integer

Dim i As Integer

S = 0

i = 1

Do Until i > 10

S = S + i ^ 2

i = i + 1

Loop

MsgBox (S)

End Sub

4 Набрать в стандартном модуле проекта следующую пользовательскую процедуру, используя цикл с постусловием While :

Sub summa()

Dim S As Integer

Dim i As Integer

S = 0

i = 1

S = S + i ^ 2

i = i + 1

Loop While i <= 10

MsgBox (S)

End Sub

5 Набрать в стандартном модуле проекта следующую пользовательскую процедуру, используя цикл с постусловием Until :

Sub summa()

Dim S As Integer

Dim i As Integer

S = 0

i = 1

S = S + i ^ 2

i = i + 1

Loop Until i > 10

MsgBox (S )

End Sub

VBA. Организация циклов.

Операторы цикла используются для повторения выполнения действия или группы действий заданное количество раз. Количество повторений (итераций цикла) может быть предопределено или вычислено.

VBA поддерживает циклические конструкции двух видов:

  1. Циклы с фиксированным числом повторений (циклы со счетчиком ).
  2. Циклы с неопределенными числом повторений (циклы с условием ).

Для всех видов циклов используется понятие тело цикла , определяющее блок операторов, заключенных между начальным и конечным операторами цикла. Каждое повторение выполнения операторов тела цикла называется итерация .

Фиксированные циклы

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

Встречаются ситуации, когда от программы VBA требуется совершить несколько раз подряд один и тот же набор действий (то есть повторить несколько раз один и тот же блок кода). Это может быть сделано при помощи циклов VBA.

Оператор цикла «For» в Visual Basic

Структура оператора цикла For в Visual Basic может быть организована в одной из двух форм: как цикл For … Next или как цикл For Each .

Цикл «For … Next»

Цикл For … Next использует переменную, которая последовательно принимает значения из заданного диапазона. С каждой сменой значения переменной выполняются действия, заключённые в теле цикла. Это легко понять из простого примера:

For i = 1 To 10 Total = Total + iArray(i) Next i

В этом простом цикле For … Next используется переменная i , которая последовательно принимает значения 1, 2, 3, … 10, и для каждого из этих значений выполняется код VBA, находящийся внутри цикла. Таким образом, данный цикл суммирует элементы массива iArray в переменной Total .

В приведённом выше примере шаг приращения цикла не указан, поэтому для пошагового увеличения переменной i от 1 до 10 по умолчанию используется приращение 1 . Однако, в некоторых случаях требуется использовать другие значения приращения для цикла. Это можно сделать при помощи ключевого слова Step , как показано в следующем простом примере.

For d = 0 To 10 Step 0.1 dTotal = dTotal + d Next d

Так как в приведённом выше примере задан шаг приращения равный 0.1 , то переменная dTotal для каждого повторения цикла принимает значения 0.0, 0.1, 0.2, 0.3, … 9.9, 10.0.

Для определения шага цикла в VBA можно использовать отрицательную величину, например, вот так:

For i = 10 To 1 Step -1 iArray(i) = i Next i

Здесь шаг приращения равен -1 , поэтому переменная i с каждым повторением цикла принимает значения 10, 9, 8, … 1.

Цикл «For Each»

Цикл For Each похож на цикл For … Next , но вместо того, чтобы перебирать последовательность значений для переменной-счётчика, цикл For Each выполняет набор действий для каждого объекта из указанной группы объектов. В следующем примере при помощи цикла For Each выполняется перечисление всех листов в текущей рабочей книге Excel:

Dim wSheet As Worksheet For Each wSheet in Worksheets MsgBox "Найден лист: " & wSheet.Name Next wSheet

Оператор прерывания цикла «Exit For»

Оператор Exit For применяется для прерывания цикла. Как только в коде встречается этот оператор, программа завершает выполнение цикла и переходит к выполнению операторов, находящихся в коде сразу после данного цикла. Это можно использовать, например, для поиска определённого значения в массиве. Для этого при помощи цикла просматривается каждый элемент массива. Как только искомый элемент найден, просматривать остальные нет необходимости – цикл прерывается.

Применение оператора Exit For продемонстрировано в следующем примере. Здесь цикл перебирает 100 записей массива и сравнивает каждую со значением переменной dVal . Если совпадение найдено, то цикл прерывается:

For i = 1 To 100 If dValues(i) = dVal Then IndexVal = i Exit For End If Next i

Цикл «Do While» в Visual Basic

Цикл Do While выполняет блок кода до тех пор, пока выполняется заданное условие. Далее приведён пример процедуры Sub , в которой при помощи цикла Do While выводятся последовательно числа Фибоначчи не превышающие 1000:

"Процедура Sub выводит числа Фибоначчи, не превышающие 1000 Sub Fibonacci() Dim i As Integer "счётчик для обозначения позиции элемента в последовательности Dim iFib As Integer "хранит текущее значение последовательности Dim iFib_Next As Integer "хранит следующее значение последовательности Dim iStep As Integer "хранит размер следующего приращения "инициализируем переменные i и iFib_Next i = 1 iFib_Next = 0 "цикл Do While будет выполняться до тех пор, пока значение "текущего числа Фибоначчи не превысит 1000 Do While iFib_Next < 1000 If i = 1 Then "особый случай для первого элемента последовательности iStep = 1 iFib = 0 Else "сохраняем размер следующего приращения перед тем, как перезаписать "текущее значение последовательности iStep = iFib iFib = iFib_Next End If "выводим текущее число Фибоначчи в столбце A активного рабочего листа "в строке с индексом i Cells(i, 1).Value = iFib "вычисляем следующее число Фибоначчи и увеличиваем индекс позиции элемента на 1 iFib_Next = iFib + iStep i = i + 1 Loop End Sub

В приведённом примере условие iFib_Next < 1000 проверяется в начале цикла. Поэтому если бы первое значение iFib_Next было бы больше 1000, то цикл бы не выполнялся ни разу.

Другой способ реализовать цикл Do While – поместить условие не в начале, а в конце цикла. В этом случае цикл будет выполнен хотя бы раз, не зависимо от того, выполняется ли условие.

Схематично такой цикл Do While с проверяемым условием в конце будет выглядеть вот так:

Do ... Loop While iFib_Next < 1000

Цикл «Do Until» в Visual Basic

Цикл Do Until очень похож на цикл Do While : блок кода в теле цикла выполняется раз за разом до тех пор, пока заданное условие выполняется (результат условного выражения равен True ). В следующей процедуре Sub при помощи цикла Do Until извлекаются значения из всех ячеек столбца A рабочего листа до тех пор, пока в столбце не встретится пустая ячейка:

IRow = 1 Do Until IsEmpty(Cells(iRow, 1)) "Значение текущей ячейки сохраняется в массиве dCellValues dCellValues(iRow) = Cells(iRow, 1).Value iRow = iRow + 1 Loop

В приведённом выше примере условие IsEmpty(Cells(iRow, 1)) находится в начале конструкции Do Until , следовательно цикл будет выполнен хотя бы один раз, если первая взятая ячейка не пуста.

Однако, как было показано в примерах цикла Do While , в некоторых ситуациях нужно, чтобы цикл был выполнен хотя бы один раз, не зависимо от первоначального результата условного выражения. В таком случае условное выражение нужно поместить в конце цикла, вот так:

Do ... Loop Until IsEmpty(Cells(iRow, 1))

Синтаксис оператора:

For Счетчик = Начало Т o Конец [Step Шаг ]

Блок_Операторов

Next Счетчик

Здесь обозначено:

For для (обязательное ключевое словоVB);

To до (обязательное ключевое словоVB);

Блок_Операторов – один или несколько операторов, называемыхтелом цикла;

Счетчик – целая переменная, которая считает количество выполняемых циклов;

Начало, Конец – начальное и конечное значения счетчика;

Step шаг (ключевое словоVB);

Шаг – шаг изменения счетчика; может быть и отрицательным; параметр необязательный, так как если шаг равен 1, можноStepШаг опустить;

Next– следующий (обязательное ключевое словоVB, конец записи оператора цикла).

Значение счетчика (Начало, Конец) могут быть численными константами или переменными целого или вещественного типа, могут быть отрицательными или положительными числами. Чтобы тело цикла выполнилось хотя бы один раз, должно бытьНачало ≤ Конец, еслиШаг > 0, иНачало ≥ Конец, еслиШаг < 0. Как только окажется, чтоСчетчик >Конец (если Начало < Конец), выполнение цикла заканчивается. ЕслиНачало = Конец, цикл выполнится один раз;

Пример 9.1 .Вычисление функции Y = 2 – 1.5 Sinx при изменении Х с шагом 0.2 в диапазоне .

Фрагмент программы по вычислению Yи вывода аргумента Х и функцииY:

For X = 0 To 2.4 Step 0.2

Y = 2 – 1.5*Sin(X)

Чтобы понять, как работает этот цикл, приведем программу подобного цикла, созданного с помощью оператора GoTo , меток, оператора If Then .

M1: X = X + 0.2

If X <= 2.4 Then

Y = 2 – 1.5*Sin(X)

Разберем работу этой программы. Первый расчет Yнестандартный, как бы выпадает из цикла. Цикл начинается после первой передачи управленияGoToM1 на метку М1. В строке с меткой М1 аргумент Х увеличивается на шаг 0.2 и сразу идет проверка, не превышает ли новое значение Х конечного значения 2.4. Если не превышает, то расчетYповторяется с этим новым Х. Потом снова выполняется операторGoToM1 – передача управление в строку с меткой М1. Эти повторы (циклы) расчетаYзакончатся, как только Х превысит 2.4.

Теперь программу с Ifсравним с цикломFor…Next.

For X = 0 To 2.4 Step 0.2

заменяет собой две строки

M1: X = X + 0.2

If X <= 2.4 Then

Именно две последние строки кода выполняются в цикле For, но мы этого не видим. Мы закодировали их строкой сFor… Строка кодаGoTo M1 закодирована словомNext X (буквально: следующий Х). Получается компактная конструкция.

При использовании цикла For…Nextнадо научиться использовать счетчик цикла при решении различных задач. Чтобы сообразить, как можно использовать счетчик для решения задачи, надопровести анализ постановки задачи, найти закономерности изменения некоторых параметров задачи.

Пример 9.2 . Определение суммы элементов ряда: .

Фрагмент программы:

S = 0 ‘ S – сумма ряда

For i = 1 To 16 ‘ счетчик i – это знаменатель дроби

S = S + 1/i ‘ накопление суммы

Print “ S = “; S ‘ вывод суммы S на форму

При каждом значении счетчика iвыражение 1/iпоследовательно формирует элементы ряда, начиная с 1.

Пример 9.3 . Вычисление суммы ряда элементов
.

Фрагмент программы:

S = 0 ‘ S – сумма ряда

For i = 1 To 18 ‘ счетчик i – числитель

S = S + i/(i + 1) ‘ знаменатель больше числителя на 1

Print “ S = “; S ‘ вывод суммы S на форму

Пример 9.4 . Вычисление суммы: 5 + 8 + 11 + … + 32 + 35

Фрагмент программы:

S = 0 ‘ S – сумма ряда

For i = 5 To 35 Step 3 ‘ получаем арифметическую _

прогрессию со знаменателем 3

Print “ S = “; S

Пример 9.5. Вычисление суммы для заданного х:

Анализ задачи показывает, что степень при Х изменяется от 1 до 10. При этом числитель в коэффициенте при Х больше степени на 1, а знаменатель – на 2. Значение степени будем формировать с помощью счетчика i. Тогда можно составить такую программу (фрагмент):

S = 1 ‘ S – сумма ряда

For i = 1 To 10 ‘ как счетчик i, изменяется степень при Х

S = S + (-1)^i*(i + 1)*x^i / (i + 2)

Print “ S = “; S

Циклы For Next используются при вводе, выводе и обработке массивов .

Пример 9.6. Ввод и вывод значений элементов массива В(N ).

Фрагмент программы:

‘ Опускаем присваивание переменной N значения, _

введенного на форме в текстовое поле txtN:

B(i) = InputBox("Введите элемент B(" & i & ")", _

"Ввод массива B(" & N & “)”)

Print " "; B(i);

Функция InputBox () выводит на экран диалоговое окно с кнопкой закрытия, заданным сообщением, полем ввода, кнопкамиОК ,Отмена, заданным заголовком (или без него). Если будет введено число 12 – размер массиваN, то в нашем примере при первом появлении это окно будет иметь вид:

Как видим, сообщение Введите элемент В(1) предлагает ввести значение 1-го элемента в текстовое окно. Появится это окно 12 раз, так как массив содержит 12 элементов. Это следует из заголовка формы. Индекс элемента В(i) в приглашении будет меняться от 1 до 12.

Если требуется вывести на форму только значения элементов массива В(N), то тело цикла будет состоять из одного оператора:

Просмотр элементов массива для совершения над ними каких-то действий также происходит с помощью оператора цикла For…Next.

Приведем примеры обработки одномерных массивов.

Пример 9.7 . Определение максимального элемента в массиве В(M ).

Исключая ввод начальных данных и вывод результатов, кратко опишем алгоритм:

    Объявим переменную Вmaх, в которую занесем значение первого элемента массива, и переменнуюImax, которой присвоим 1 – индекс первого элемента массива.

    В цикле с помощью оператора For…Nextпросматриваем все элементы массива, начиная со 2-го. Используя операторIf…Then, сравниваем их значения со значением, которое хранится в переменнойBmax.

    Если окажется, что значение элемента массива больше величины Bmax, тоBmaxприсваиваем значение этого элемента, а значениюImax– индекс этого элемента массива.

После окончания цикла в переменной Bmaxокажется значение максимального элемента, а вImax– его индекс (номер).

Программа этой части алгоритма.

Bmax = B(1): Imax = 1

If B(i) > Bmax Then Bmax = B(i): Imax = i

Пример 9.8. Определение суммы, произведения и количества положительных элементов массива D (M ).

Переменные: S,P,K– соответственно сумма, произведение и количество положительных элементов.

Алгоритм такого определения:

    Присваиваем ноль переменной Sи К, переменнойPприсваиваем 1. Как правило, всегда переменные, где накапливается сумма, здесь этоSиk, перед циклом обнуляются, а переменным, в которых вычисляется произведение, присваивается 1.

    С помощью цикла For…Nextперебираем все элементы массива и проверяем положительные ли они (D(i) > 0).

    Если окажется, что элемент – положительный, то прибавляем его значение к значению суммы Sи сохраняем новую сумму в этой же переменной. ПеременнуюPумножаем на положительное значение элемента и сохраняем также в переменнойP. А к переменнойKприбавляем 1 и сохраняем новое значение в этой же переменной

Программа этой части алгоритма имеет вид:

S = 0: P = 1: K = 0

If D(i) > 0 Then

S = S + D(i) ‘ так происходит накопление суммы _

положительных значений элементов массива D(i)

P = P*D(i) ‘ определение произведения положительных

‘ элементов массива

K = K + 1 ‘ этот оператор называют СЧЕТЧИКОМ, здесь он

‘ определяет количество положительных элементов массива

Пример 9.9. Определение суммы, произведения, количества и среднего значения нечетных элементов массива D (M ).

Приведем фрагмент программы такого определения.

S = 0: P = 1: K = 0

If D(i) Mod 2 <> 0 Then

Ssr = S/k ‘ вычисление среднего значения нечетных элементов

Сравните этот фрагмент программы с программой Примера 9.8. Эта программа почти полностью повторяет предыдущую. Изменено только условие в операторе If. УсловиеD(i) Mod 2 <> 0 означает, что мы ищем элементы массиваD(i), которые не делятся нацело на 2, т. е. нечетные элементы. Если будем проверять условиеD(i) Mod 2 = 0, то мы будем отбирать четные элементы массива.

Как известно, деление по Mod даетв результате остаток от деления в целых числах. Например, после выполнения оператораd= 34Mod4 переменнаяdбудет равна 2. Поэтому для отбора элементов массива, которые кратны 4, надо проверять условиеD(i) Mod 4 = 0. Аналогичным будет условие, если будем искать элементы, кратные другим числам. Вместо 4 будут записаны эти другие числа.

Пример 9.10. Запись элементов массива R (N ), кратных 5, в другой массив и вывод нового массива на форму.

Другой массив обозначим, например, R5(N). Размер этого нового массива следует принять таким же, как исходный, т. к. в предельном случае все элементы могут быть кратными 5.

Алгоритм задачи:

    Обнуляем счетчик k. С помощью оператора циклаFor…Nextпросматриваем все элементы массиваR(N).

    Каждый элемент проверяем на кратность 5, используя оператор If…Thenи деление элемента массива поMod.

    Если элемент кратен 5, то с помощью счетчика типа k=k+ 1 формируем индексы массиваR5(N), начиная с 1, и записываем его в этот другой массив –R5(N).

    Если kотлично от нуля, выводим массивR5() на форму.

    Если же kравно нулю выводим: «Нет элементов, кратных 5».

Фрагмент программы:

If R(i) Mod 5 Then k = k + 1: R5(k) = R(i)

If k <> 0 Then

Print “Нет элементов, кратных 5”

Циклы могут быть вложенными в другие циклы.

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

Private Sub frmCycle_DblClick()

ScaleMode = 4 ‘единицы измерения – символы

For i = 1 To 3 ‘внешний цикл

Print "i = "; i;

For j = 1 To 4 ‘1-й вложенный цикл

CurrentX = TextWidth("i = 1 ") + 5

Print "j = "; j;

CurrentX = TextWidth("i = 1 j = 1 ") + 7

For k = 1 To 5 ‘2-й вложенный цикл

На изображенной форме (рис. 1) приведены результаты вывода счетчиков всех трех циклов: внешнего цикла – счетчик i, первого вложенного цикла – счетчикjи второго, самого внутреннего цикла – счетчикk. Как видим,самый «медленный» счетчик у внешнего цикла (поi), асамый «быстрый» – счетчик самого внутреннего цикла (по k ).

Программа выполняется после двойного щелчка левой кнопкой мыши по форме frmCicli.

CurrentX, CurrentY – свойства формы, задающие координатыX,Yточки начала вывода информации методомPrint(см. на рис.1 расположение осейXиYна форме).

TextWidth() – функция, возвращающая ширину текста, заданного в функции как аргумент в двойных кавычках.

Вложенные циклы используются при обработке двумерных массивов (матриц). Но в некоторых задачах, исключая ввод и вывод элементов двумерного массива, можно ограничиться и одним циклом. Рассмотрим некоторые примеры программирования матриц.

Пример 9.11. Ввод и вывод матрицы (двумерного массива) целых чисел intA (N ).

Вводить матрицу можно по строкам и по столбцам . Проще – по строкам, если будет программироваться вывод элементов массива на форму сразу после их ввода.

Ввод и вывод матрицы по строкам – фрагмент 1 .

Dim M As Integer, N As Integer, i As Integer, j As Integer

Dim intA() As Integer ‘ объявляем динамический массив

M = Val(txtN.Text) ‘ M – количество строк

N = Val(txtN.Text) ‘ N – количество столбцов

ReDim intA(M, N) As Integer ‘ переопределяем массив

For i = 1 To M ‘ i будет сохранять свое значение, пока полностью

‘не выполнится вложенный цикл по j

Print " "; intA(i, j); ‘ вывод по строкам

Print ‘ переход в начало новой строки

Чтобы вводить матрицу по столбцам, следует внешним сделать цикл по j(задает номера столбцов), а внутренним – цикл поi(задает номера строк).

Ввод и вывод матрицы по столбцам фрагмент 2 .

PrY = 2500: CurrentY = PrY ‘ PrY задает координату Y начала

‘ вывода первого элемента каждого столбца на форме

For j = 1 To N ‘ j будет сохранять свое значение, пока полностью

‘не выполнится вложенный цикл по i

intA (i, j) = InputBox("Введите элемент intA(" & i & “,” & j & ")", _

"Ввод матрицы intA(" & M & “,” & N & ")")

Print Tab(6 * j); intA(i, j) ‘ вывод по столбцам

CurrentY = PrY ‘ для вывода первого элемента

‘ следующего столбца

В этом втором фрагменте программы не повторяются 5 первых строк из первого фрагмента. Функция Tab(6 * j) устанавливает начало вывода в строке (в символах), начиная от левого края формы. КоординатаPrYздесь равна 2500 твипов, но можно подобрать и другое значение.

Пример 9.12 . Упорядочивание значений элементов массива V (N ) по возрастанию.

Существуют несколько алгоритмов по упорядочиванию массивов. Приведем один из них: с помощью вложенных циклов For Next выбираем элементы, начиная с первого и до предпоследнего, и сравниваем каждый из них с последующими элементами; если окажется, что последующий элемент меньше выбранного, меняем их местами.

Фрагмент программы, реализующей этот алгоритм:

For i = 1 To N – 1

For j = i + 1 To N

If V(j) < V(i) Then P = V(i): V(i) = V(j): V(j) = P

Поясним этот фрагмент программы.

С помощью внешнего цикла со счетчиком iвыбираем элементV(i) для сравнения с последующими элементами. Внутренний цикл со счетчикомjвыбирает для сравнения последующие элементыV(j). Начальное значениеjравноi+ 1. Это первый элемент из последующих.

Для обмена значений элементов V(i) иV(j) вводим некоторую переменнуюP, в которую временно «прячем» значение одного из элементов массива (в программе – этоV(i)). Затем элементу V(i) присваиваем значение элементаV(j), а элементуV(j) присваиваем значениеV(i), которое хранится в переменнойP. Если «спрячем» вPзначениеV(j), то код по обмену значениями будет таким:P = V(j): V(j) = V(i): V(i) = P. Результат не изменится.

Чтобы упорядочить массив по убыванию , достаточно условие для проверки написать в видеV(j) > V(i), т. е. изменить знак неравенства на другой.

Если массив будет не числовой, а строковый, и в элементы массива будут введены фамилии, то по программе примера 9.12, можно упорядочить список фамилий по алфавиту. Дело в том, что для букв алфавита, используемых в компьютере, справедливы неравенства: А < Б < В < Г….< Я и т. д., поскольку числовые коды букв алфавита последовательно увеличиваются, начиная с А и до конца алфавита. Это же справедливо и для букв английского алфавита.

Пример 9.13 . Вычисление суммы положительных элементов для нечетных столбцов матрицы F (M , N ) и вывод сумм на форму.

Алгоритм программы:

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

    Обнуляем сумму S, в которой будет накапливаться сумма положительных элементов.

    Во внутреннем цикле проверяем знак элемента массива.

    Если элемент массива положителен (> 0), вычисляем сумму S.

    После окончания внутреннего цикла выводим сумму Sна форму.

Фрагмент программы :

For j = 1 To N Step 2

If F(i, j) > 0 Then S = S + F(i, j)

Print “Сумма столбца “; j; “:”; S ‘ j – номер столбца!

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

Пример 9.14. Имеется 1801 руб. Сколько можно купить шоколадок по 31 руб. и булок по 18 руб., чтобы полностью потратить все деньги.

Программа:

Сумма = 1801

ВсеШоколадки = Сумма \ 31: ВсеБулки = Сумма \ 18

For i = 1 To ВсеШоколадки

For j = 1 To ВсеБулки

Цена = i * 31 + j * 18 ‘общая цена покупки

If Цена = 1801 Then

Print "Шоколадок: "; i; Tab(19); "Булок: "; j

Поясним программу, в которой используем переменные, названные по-русски.

Сначала определяем, какое максимальное количество только шоколадок или только булок можно купить на всю сумму. Полученные значения ВсеШоколадки и ВсеБулки используем для ограничения количеств переборов по количеству шоколадок и булок. Для каждых значений количества шоколадок (i) и количество булок (j) определяем общую Цену для их покупки. Если рассчитанная Цена равна 1801, то подобранный вариант есть одно из решений задачи.

Функция Tab() указывает, с какой позиции от края формы будет вывод информации, следующий за этой функцией. ЕслиTab(19), то с 19-ой позиции.

Программа выводит 3 возможных вариантов покупки:

Шоколадок 7, булок 88

Шоколадок 25, булок 57

Шоколадок 43, булок 26

Если требуется дать однозначный ответ, надо сформулировать дополнительное условие. Например, «булок было куплено меньше, чем шоколадок». Тогда единственным решением будет 3-й вариант.

Существует много математических задач, которые просто решаются методом перебора с помощью программирования вложенных циклов.

Циклы позволяют выполнить одну или несколько строк кода несколько раз. VBA поддерживает следующие циклы:

For...Next For Each...Next Do... Loop

Конструкция For . . . Next. Когда число повторений известно заранее, используют цикл For . . . Next. В цикле For используется переменная, называемая переменной цикла или счетчиком цикла, которая увеличивается или уменьшается на заданную величину при каждом повторении цикла. Синтаксис этой конструкции следующий:

For counter = start To end операторы Next

Параметры counter (счетчик), start (начало цикла), end (конец цикла) и increment (приращение) являются числовыми.

Примечание. Параметр increment может быть как положительным, так и отрицательным. Если он положителен, параметр start должен быть меньше или равен параметру end, иначе цикл не будет выполняться. Если параметр increment отрицателен, то параметр start должен быть больше или равен значению параметра end, чтобы выполнялось тело цикла. Если параметр Step не задан, то значение параметра increment по умолчанию равно 1.

VBA выполняет цикл For в следующей последовательности:

1. Устанавливает значение переменной цикла counter в значение start.

2. Сравнивает значение переменной цикла counter и значение параметра end. Если переменная counter больше, VBA завершает выполнение цикла. (Если значение параметра increment отрицательно, то VBA прекращает выполнение цикла при условии, что значение переменной цикла counter меньше значения параметра end.)

3. Выполняет операторы тела цикла statements.

4. Увеличивает значение переменной цикла counter на 1 или на величину значения параметра increment, если он задан.

5. Повторяет шаги со 2 по 4.

Рассмотрим пример: Вычислить значение функции f(t)

при заданных a, b, n, если t изменяется от a до b с шагом Dt=(b-a)/(n-1).

Sub пример3() Dim f() As Single Dim a As Single, b As Single, t As Single, dt As Single Dim i As Integer, n As Integer Call read("a1", a) : Call read("b1", b) : Call read("c1", n) ReDim f(1 To n - 1) dt = (b - a) / (n - 1) : t = a Call out("a2", "i") : Call out("b2", "t") : Call out("c2", "f(t)") For i = 1 To n - 1 t = t + dt If t <= -1 Then f(i) = -1 ElseIf t > 1 Then f(i) = 1 Else f(i) = t End If Call out("a" & (2 + i), i) : Call out("b" & (2 + i), t) : Call out("c" & (2 + i), f(i)) Next i End Sub

Конструкция For Each . . . Next

Цикл For Each . . . Next похож на цикл For . . . Next, но он повторяет группу операторов для каждого элемента из набора объектов или из массива, вместо повторения операторов заданное число раз. Он особенно полезен, когда неизвестно, сколько элементов содержится в наборе.

Синтаксис конструкции цикла For Each . . . Next таков:

For Each element In group операторы Next element

Следует помнить следующие ограничения при использовании цикла For Each . . . Next:

Для наборов параметр element может быть только переменной типа variant, общей переменной типа object или объектом, перечисленным в Object Browser

Для массивов параметр element может быть только переменной типа Variant

Нельзя использовать цикл For Each . . . Next с массивом, имеющим определенный пользователем тип, так как переменная типа variant не может содержать значение определенного пользователем типа

Конструкция Do...Loop

Цикл Do применяется для выполнения блока операторов неограниченное число раз. Существует несколько разновидностей конструкции Do . . . Loop, но каждая из них вычисляет выражение-условие, чтобы определить момент выхода из цикла. Как и в случае конструкции If . . . Then условие должно быть величиной или выражением, принимающими значение False (нуль) или True (не нуль).

В следующей конструкции Do . . . Loop операторы выполняются до тех пор, пока значением условия является True (Истина):

Do While условие операторы Loop

Выполняя этот цикл, VBA сначала проверяет условие. Если условие ложно (False), он пропускает все операторы цикла. Если оно истинно (True), VBA выполняет операторы цикла, снова возвращается к оператору Do While и снова проверяет условие.

Следовательно, цикл, представленный данной конструкцией, может выполняться любое число раз, пока значением условия является не нуль или True (Истина). Отметим, что операторы тела цикла не выполняются ни разу, если при первой проверке условия оно оказывается ложным (False).

Рассмотрим пример: Вычислить сумму ряда

с заданной точностью.

Sub пример4() Dim e As Single, x As Single, s As Single Dim m As Single, p As Single, i As Single Call read("a1", x) : Call read("b1", e) s = 0: i = 1: m = 1: p = -1 Call out("a2", "i") : Call out("b2", "m") : Call out("c2", "s") Do While Abs(m) >= e p = -p * x m = p / i s = s + m Call out("a" & (2 + i), i) : Call out("b" & (2 + i), Abs(m)) : Call out("c" & (2 + i), s) i = i + 1 Loop End Sub

Другая разновидность конструкции Do . . . Loop сначала выполняет операторы тела цикла, а затем проверяет условие после каждого выполнения. Эта разновидность гарантирует, что операторы тела цикла выполнятся по крайней мере один раз:

Do операторы Loop While условие

Две другие разновидности конструкции цикла аналогичны предыдущим, за исключением того, что цикл выполняется, пока условие ложно (False):

Цикл не выполняется вообще или выполняется много раз:

Do Until условие

операторы Loop

Цикл выполняется по крайней мере один раз:

операторы

Loop Until условие

7.2 Вложенные циклы.

Можно помещать структуры управления внутрь других структур управления (например, блок If . . . Then внутрь цикла For . . . Next). Говорят, что структура управления, помещенная внутрь другой структуры управления, является вложенной.

Глубина вложения управляющих структур в VBA не ограничена. Для улучшения читаемости кода принята практика смещения тела конструкции принятия решения или цикла в программе в случае использования вложенных структур управления.

При вложении в цикл одного или несколько других циклов говорят о вложенных циклах, в которых различают внешние (охватывающие) и внутренние (вложенные) циклы.

Рассмотрим пример суммирования элементов Aij матрицы A(n,m) построчно.

Sub пример5() Dim a() As Single, s() As Single Dim n As Integer, m As Integer Dim i As Integer, j As Integer Call read("a1", n): Call read("b1", m) ReDim a(1 To n, 1 To m), s(1 To n) "Чтение матрицы For i = 1 To n For j = 1 To m Call readcell(i + 1, j, a(i, j)) Next j Next i "Вычисление For i = 1 To n s(i) = 0 For j = 1 To m s(i) = s(i) + a(i, j) Next j Call outcell(i + 1, m + 1, s(i)) Next i End Sub

Заметим, что первый оператор Next закрывает внутренний цикл For, а последний оператор Next закрывает внешний цикл For. Точно так же и для вложенных операторов If, операторы End If автоматически применяются для закрытия ближайшего к нему оператора If. Вложенные структуры Do . . . Loop работают подобным же образом: самый дальний оператор Loop соответствует самому дальнему оператору Do.

При вводе/выводе элементов двумерного массива на рабочий лист Microsoft Excel удобно применять пользовательские процедуры ввода/вывода:

Sub readcell(i As Integer, j As Integer, val As Variant) val = Лист1.Cells(i, j).Value End Sub Sub outcell(i As Integer, j As Integer, val As Variant) Лист1.Cells(i, j).Value = val End Sub

где I - номер строки, j - номер столбца рабочего листа.

Выход из структур управления

Оператор Exit позволяет выходить непосредственно из цикла For, цикла Do, процедуры Sub или процедуры Function. Синтаксис оператора Exit прост:

For counter = start To end [блок операторов] [блок операторов] Next Do [(While | Until} условие] [блок операторов] [блок операторов] Loop

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

Оператор Exit Do работает со всеми разновидностями синтаксиса цикла Do.

Операторы Exit For и Exit Do применяются, если необходимо завершить цикл немедленно, не продолжая дальнейших итераций или не ожидая выполнения блока операторов в теле цикла.

При использовании оператора Exit для выхода из цикла значения переменной цикла зависят от того, каким образом завершается выполнение цикла:

При нормальном завершении цикла значение переменной цикла имеет на единицу больше верхней границы числа циклов

При преждевременном завершении цикла переменная цикла сохраняет свое значение, которое она получила с учетом обычных правил

При завершении цикла по концу набора переменная цикла имеет значение Nothing (Ничего), если она является переменной типа object (Объект), или значение Empty (Пусто), если она является переменной типа Variant



Понравилась статья? Поделиться с друзьями: