Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SrrazOffpril_Vecher.rtf
Скачиваний:
9
Добавлен:
18.09.2019
Размер:
1.9 Mб
Скачать
    1. Управляющие конструкции

1.3.1. Операторы ветвления

Управляющая конструкция If…Then позволяет выполнять один или несколько операторов, если условие истинно. Можно использовать однострочный и блочный синтаксис. Например:

If thisVal < 0 Then thisVal = 0

If thisVal > 5 Then

thatVal = thisVal + 25

thisVal = 0

End if

В однострочной форме оператор End If не применяется. Если необходимо выполнить более одной строки кода, когда оценка условного выражения дает True, применяется блочный вариант – If … Then … End If.

Если в условии содержатся два выражения, объединенных оператором Or, то проверяется оба выражения, даже если первое уже True. Иногда это влияет на результат работы оператора; если переменная во втором выражении содержит неверное значение, в период выполнения может возникнуть ошибка.

Оператор ветвления If…Then…Else позволяет определить два блока оператора. Первый блок выполняется, когда условие истинно, а второй – когда оно ложно. Пример:

If age < 16 Then

MsgBox “You are not old enough for a license”

Else

MsgBox “You can be tested for a license”

End If

Для проверки дополнительных условий не обязательно вкладывать операторы If … Then друг в друга – можно добавить операторы ElseIf, тогда код программы станет более читаемым и лаконичным. Допустим, по условию задачи необходимо рассчитать премии сотрудникам с учетом их вклада в общее дело. Процедура типа Function из следующего примера использует для этого серию операторов ElseIf:

Function Bonus(jobClass, salary, rating)

If jobClass = 1 Then

Bonus = salary * 0.1 * rating / 10

ElseIf jobClass = 2 Then

Bonus = salary * 0.09 * rating / 10

ElseIf jobClass = 3 Then

Bonus = salary * 0.07 * rating / 10

Else

Bonus = 0

End If

End Function

Оператор If … Then … ElseIf очень гибок. Можно начать с простого оператора If … Then, а потом добавлять операторы Else и ElseIf по мере необходимости. Но если все операторы ElseIf сравнивают одно и то же выражение с разными значениями, лучше воспользоваться оператором Select Case.

Оператор ветвления Select Case заменяет серию операторов ElseIf в том случае, когда одно выражение сравнивается с несколькими значениями. Он обеспечивает ветвление по условию, аналогичное возможностям оператора If … Then … ElseIf; но делает код эффективнее и читабельнее. Например, чтобы добавить еще несколько уровней в предыдущий пример фрагмента кода, можно было бы ввести дополнительные операторы ElseIf, однако лучше переписать эту функцию на основе оператора Select Case:

Function Bonus(jobClass, salary, rating)

Select Case jobClass

Case 1

Bonus = salary * 0.1 * rating / 10

Case 2

Bonus = salary * 0.09 * rating / 10

Case 3

Bonus = salary * 0.07 * rating / 10

Case 4, 5 ‘можно включать несколько значений…

Bonus = salary * 0.05 * rating / 5

Case 6 To 8 ‘…или задавать диапазон

Bonus = 150

Case Is > 8 ’…или сравнивать с другими значениями

Bonus = 100

Case Else

Bonus = 0

End Select

End Function

В конструкции Select Case вычисляется только одно выражение – в самом ее начале. Оператор If … Then … ElseIf, напротив, позволяет проверять разные выражения в каждом ElseIf. Поэтому оператор If … Then … ElseIf можно заменить оператором Select Case, только если все ElseIf вычисляют одно выражение.

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

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

Оператор Do While … Loop позволяет проверить условие перед началом цикла и выполняет цикл, пока оно истинно (True). Проверяемое в цикле Do While … Loop условие рано или поздно должно стать False, иначе цикл будет бесконечным. Чтобы остановить бесконечный цикл, предусмотрено сочетание клавиш Ctrl + Break. Процедура Function из следующего примера подсчитывает число вхождений одной строки в другую, выполняя цикл до тех пор, пока не будут найдены все вхождения. Поскольку проверка осуществляется в начале цикла, тот выполняется, только если заданная строка присутствует в другой строке:

Function CountStrings(longstring, target)

Position = 1

возвращает True или False

Do While InStr(position, longstring, target)

Position = IntStr(position, longstring, target) + 1

Count = Count + 1

Loop

CountString = Count

End Function

Оператор Do Until … Loop позволяет проверять условие в самом начале цикла и продолжает выполнять цикл, пока оно не окажется истинным (True). Если окажется, что условие выполнено в самом начале цикла (даст True), то операторы в теле цикла пропускаются. В следующем примере цикл не выполняется, если Response равна vbNo:

Response = MsgBox (“Do you want to process more data?”, vbYesNo)

Do Until Response = vbNo

ProcessUserData ‘вызываем процедуру для обработки данных

Response = MsgBox (“Do you want to process more data?”, vbYesNo)

Loop

Если операторы цикла следует выполнить хотя бы раз, используется оператор Do … Loop While, который позволяет проверять условие в конце цикла. Операторы выполняются пока условие истинно. В следующем примере для Microsoft Excel цикл повторяется, только если метод Find находит ячейку со строкой «test». Если текст найден, ячейка выделяется синим цветом, и продолжается поиск следующей строки «test». Если таких строк больше нет, цикл завершается:

Sub MakeBlue()

Set rSearch = Worksheet (“sheet1”).Range (“a1:a10”)

Set c = rSearch. Find (“test”)

If Not c Is Nothing Then

first = c.Address

Do

c.Font.ColorIndex = 5

Set c = rsearch.FindNext (c)

Loop While (Not c Is Nothing) And (c.Address <> first)

Else

MsgBox “Not found”

End If

End Sub

В конструкции Do … Loop Until проверка осуществляется в конце цикла, поэтому цикл выполняется минимум один раз и прекращается, когда условие становится истинно (True):

Do

ProcessUserData ‘вызываем процедуру для обработки данных

Response = MsgBox (“Do you want to process more data?”, vbYesNo)

Loop Until Response = vbNo

Если заранее известно, что какой-то блок кода надо повторить определенное число раз, используется цикл For … Next. В отличие от операторов серии Do … Loop, в данном операторе используется счетчик, уменьшаемый или увеличиваемый на каждой итерации цикла. Если разновидности оператора Do … Loop завершают цикл, как только условие становится истинным или ложным, то цикл For … Next прекращается, как только счетчик достигает заданного значения. Приведенная ниже процедура Sub генерирует сигнал заданное число раз:

Sub BeepSeveral()

numBeeps = InputBox(“How many beeps?”)

For counter = 1 To numBeeps

Beep

Next counter

End Sub

По умолчанию (как и в этом примере) счетчик увеличивается на каждой итерации цикла на единицу. Ключевое слово Step позволяет изменить шаг приращения, если указывается отрицательное число - счетчик уменьшается на каждой итерации цикла. Пример процедуры Sub, использующей цикл с шагом приращения счетчика равным двум:

Sub ClearArray(ByRef ArrayToClear())

For i = LBound(ArrayToClear) To UBound(ArrayToClear) Step 2

ArrayToClear(i) = 0

Next i

End Sub

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

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

For Each элемент In группа

операторы

Next элемент

Встретив оператор For Each … Next, Visual Basic:

  1. Считает элемент именем первого элемента в группе (если группа не пуста).

  2. Выполняет операторы.

  3. Проверяет, не последний ли это элемент в группе, и, если да, завершает цикл.

  4. Подставляет вместо элемента имя следующего элемента в группе.

  5. Повторяет операции, описанные в пунктах 2-4 данной последовательности.

В следующем примере, для Microsoft Excel, проверяется каждая ячейка текущего региона для ячейки А1 в таблице с именем «Sheet3» и закрашивается содержимое ячейки красным цветом, если ее значение меньше -1:

For Each c In Worksheets(“sheet3”).Range(“a1”).CurrentRegion.Cells

If c.Value < -1 Then c.Font.ColorIndex = 3

Next c

А в примере для Word просматриваются все исправления в выделенном тексте и поочередно принимаются:

For Each myRev In Selection.Range.Revisions

myRev.Accept

Next myRev

Указывать имя переменной после Next не обязательно, но это облегчает восприятие текста в программе, особенно при наличии нескольких встроенных циклов For Each.

Если необходимо удалить все объекты из набора, следует использовать цикл For … Next, а не For Each … Next. Например, необходимо удалить все слайды из текущей презентации:

Set allSlides = ActivePresentation.Slides

For s = allSlides.Count To 1 Step -1

allSlides.Item(s).Delete

Next

Но код, приведенный ниже, работать не будет – он удалит каждый второй слайд в презентации:

For Each s In ActivePresentation.Slides

s.Delete

Next

Применяя оператор For Each … Next, следует помнить о следующих ограничениях:

  • в случае наборов элементом может быть переменная типа Variant, Object или конкретного объектного типа из библиотеки объектов, а для массивов – только Variant;

  • оператор For Each … Next не годится для массивов пользовательских типов, так как в переменную типа Variant нельзя записать значение пользовательского типа.

1.3.3. Вложение управляющих конструкций

Управляющие конструкции можно включать друг в друга, например, вставить блок If … Then внутрь цикла For Each … Next, который в свою очередь находится в другом блоке If … Then и т.д. Такие конструкции называются вложенными.

В следующем примере просматривается заданный диапазон ячеек и подсчитывается число ячеек, содержащих определенное значение:

Function CountValues(rangeToSearch, searchValue)

If TypeName(rangeToSearch) <> “Range” Then

MsgBox “You can search only a range of cells”

Else

For Each c In rangeToSearch.cells

If c.Value = searchValue Then

counter = counter + 1

End If

Next c

End If

CountValues = counter

End Function

Первый оператор End If закрывает внутренний блок If … Then, а последний оператор End If – внешний. По аналогии, в случае вложенных циклов For … Next и For Each … Next операторы Next автоматически применяются к ближайшему предыдущему оператору For или For Each. Вложенные конструкции Do … Loop ведут себя сходным образом.

1.3.4. Выход из циклов и процедур

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

Например, осуществляя поиск в массиве в цикле For … Next и найдя нужное значение уже на первой итерации, нет смысла просматривать остальную часть массива – разумнее тут же прекратить цикл и перейти к следующим за ним оператором. Если при выполнении процедуры происходит ошибка, делающая бессмысленным выполнение остальных ее операторов, то, естественно, надо немедленно выйти из процедуры. Для таких случаев предназначен оператор Exit.

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

Кроме того, для пропуска части кода можно придумать и более подходящие способы. Например, при поиске значения в массиве внутрь цикла For … Next вместо оператора Exit можно поставить оператор Do … Loop, чтобы поиск шел только до тех пор, пока текущее значение индекса меньше верхней границы массива и значение переменной типа Boolean равно False. Когда искомое значение найдено, переменная типа Boolean устанавливается как True, и цикл прекращается:

i = LBound(searchArray)

ub = UBound(searchArray)

foundIt = False

Do

If searchArray(i) = findThis Then foundIt = True

i = i + 1

Loop While i <= ub And Not foundIt

Для досрочного выхода из оператора Do … Loop используется оператор Exit Loop, а для досрочного выхода из цикла For – оператор Exit For:

For Each c In rangeToSearch

If c.Value = searchValue Then

found = True

Exit For

End If

Next

Для досрочного выхода из процедур служат операторы Exit Sub и Exit Function:

For Each c In rangeToSearch

If c.Value = searchValue Then

counter = counter + 1

ElseIf c.Value = “Bad Data” Then

countValues = Null

Exit Function ‘прекратить проверку и немедленно выйти

End If

Next c

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]