Циклы

В VBA имеется богатый выбор средств организации циклов, которые можно разделить на две основные группы — циклы с условием Do... Loop и циклы с перечислением for...Next.

Циклы типа Do ... Loop используются в тех случаях, когда заранее неизвестно, сколько раз должно быть повторено выполнение блока операторов, составляющего тело цикла. Такой цикл продолжает свою работу до тех пор, пока не будет выполнено определенное условие. Существуют четыре вида циклов Do...Loop, которые различаются типом проверяемого условия и временем выполнения этой проверки. В табл. 13.2 приводится синтаксис этих четырех конструкций.

Таблица 13.2. Синтаксис операторов цикла Do

Конструкция

Описание

Do While <условие> <блокОператоров> Loop


Условие проверяется до того, как выполняется группа операторов, образующих тело цикла. Цикл продолжает свою работу, пока это условие выполняется (то есть имеет значение True), иными словами, в этой конструкции указывается условие продолжения работы цикла


Do Until <условие> <блокОператоров> Loop Условие проверяется до того, как выполняется группа операторов, образующих тело цикла. Цикл продолжает свою работу, если это условие еще не выполнено, и прекращает работу, когда оно станет истинным, иными словами, в этой конструкции указывается условие прекращения работы цикла
Do <блокОператоров> Loop Until <условие> Условие проверяется после того, как операторы, составляющие тело цикла, будут выполнены хотя бы один раз. Цикл продолжает свою работу, если это условие еще не выполнено, а когда оно станет истинным, цикл прекращает работу, иными словами, в этой конструкции указывается условие прекращения работы цикла

Do

<блокОператоров> Loop While <условие>

Условие проверяется после того, как операторы, составляющие тело цикла, будут выполнены хотя бы один раз. Цикл продолжает свою работу, пока это условие остается истинным, иными словами, в этой конструкции указывается условие продолжения работы цикла

 

Имеется также две разновидности оператора цикла с перечислением for. . .Next. Очень часто при обработке массивов, а также в тех случаях, когда требуется повторить выполнение некоторой группы операторов заданное число раз, используется цикл for. . .Next со счетчиком. В отличие от циклов Do. . .Loop, данный тип цикла использует специальную переменную, называемую счетчиком, значение которой увеличивается или уменьшается при каждом выполнении тела цикла на определенную величину. Когда значение этой переменной достигает заданного значения, выполнение цикла заканчивается.

Синтаксис этого вида цикла выглядит, следующим образом (в квадратные скобки заключены необязательные элементы синтаксической конструкции):

for <счетчик> = <начальноеЗначение>

То <конечноеЗначение>

[Step <приращение>]

<блокОператоров> Next [<счетчик>]

Несколько пояснений к приведенному описанию:

Рассмотрим еще одну разновидность цикла for. . .Next, часто использующуюся в VBA при обработке объектов, составляющих массив или семейство однородных объектов. В этой разновидности цикла счетчик отсутствует, а тело цикла выполняется для каждого элемента массива или семейства объектов. Вот синтаксис такого цикла:

for Each <элемент> In <совокупность>

<блокОператоров>

Next [<элемент>]

где:

<элемент> — это переменная, используемая для ссылки на элементы семейства объектов;

<совокупность> — это имя массива или семейства.

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

Public Sub EnumerateAllFields()

Dim MyBase As Database

Dim tdf As TableDef, fid As Field

Set MyBase = CurrentDb()

for Each tdf In MyBase.TableDefs

Debug.Print "Таблица: " & tdf.Name

for Each fid In tdf.Fields

Debug.Print " Поле: " & fid.Name Next fid

Next tdf

Set MyBase = Nothing

End Sub

Итак, в операторах Dim мы объявили переменную MyBase как объект "база данных DАО", переменные tdf и fid — как определение таблицы и поле таблицы, соответственно. Оператор Set назначает переменной MyBase текущую открытую базу данных. Далее для каждого определения таблицы выполняется вывод на печать названия таблицы, а затем вложенный цикл такого же типа печатает названия всех ее полей.

Приведем еще один пример использования подобного оператора цикла for Each. . .Next для обработки всех элементов многомерного массива. Пусть у нас имеется трехмерный числовой массив из 1000 элементов (размерами 10x10x10), который мы хотим заполнить случайными вещественными числами в диапазоне от 0 до 1. Если бы мы применяли обычные циклы for. . .Next со счетчиками, используя счетчики в качестве индексов элементов массива, то для решения этой задачи потребовалось бы написать три вложенных цикла for. . . Next:

Dim tArray{9, 9, 9) As Single

Dim i%, j%, k%

Randomize

for i=0 To 9

for j=0 To 9

for k=0 To 9

tArray(i, j, k) = Rnd()

Next k

Next j

Next i

На самом же деле достаточно всего одного цикла, если вместо циклов со счетчиками воспользоваться циклом for Each . . . Next:

Dim tArray(9, 9, 9) As Single

Dim elem As Variant

Randomize

for Each elem In tArray

elem = Rnd()

Next

Еще раз порекомендуем использовать отступы при записи циклов, так же, как и при записи операторов ветвления.