Microsoft Office (Разработка документов в Word, Excel и приложений на Visual Basic for Application). - Учебное пособие (Н.А.Устинов)

Статические процедуры и функции.

Процедуры и функции могут быть описаны как статические, при этом все переменные этих процедур и функций также становятся статическими

Примеры, относящиеся к вышеизложенному материалу, находятся в книге lect12.XLS в модуле VisVar.

Описание констант

При описании константы ей можно присвоить значащее имя. Инструкция Const используется для описания константы и определения ее значения. После описания константу нельзя модифицировать и нельзя присваивать ей новое значение.

Константа описывается в процедуре или в начале модуля, в разделе описаний. Константы уровня модуля по умолчанию являются личными. При описании общих констант уровня модуля инструкции Const должно предшествовать ключевое слово Public. Для явного описания личных констант перед инструкцией Const надо поставить ключевое слово Private. Это облегчает чтение и отладку программы.

В следующем примере константа Public conAge описывается как Integer, и ей присваивается значение 34.

Public Const conAge As Integer = 34

Константы могут быть описаны одним из следующих типов данных: Boolean, Byte, Integer, Long, Currency, Single, Double, Date, String, или Variant. Поскольку значение константы уже известно, можно задать тип данных в инструкции Const. Дополнительные сведения содержатся в разделе "Типы данных" справочника Visual Basic.

Допускается также описание нескольких констант в одной строке. В этом случае, чтобы задать тип данных, надо указать определенный тип для каждой константы. В следующем примере константы conAge и conWage описываются как Integer.

Const conAge As Integer = 34, conWage As Currency = 35000

Устранение конфликтов имен

При попытке создать или использовать идентификатор, определенный ранее, возникает конфликт имен. В некоторых случаях при конфликтах имен вырабатываются ошибки типа "Обнаружено повторяющееся имя" или "Повторяющееся описание в текущей области определения". Если конфликты имен не обнаружены, они могут привести к ошибкам в программе, и, как следствие, к ошибочным результатам. Это особенно вероятно в том случае, если все переменные не были описаны явным образом до их применения.

Для предотвращения большинства конфликтов имен необходимо аккуратно разобраться с областями определения идентификаторов для данных, объектов и процедур. Язык Visual Basic имеет три уровня областей определения: уровень процедуры, личный уровень модуля и общий уровень модуля.

Конфликты имен могут возникать, если идентификатор:

·        Является видимым более чем на одном уровне областей определения.

·        Имеет на одном и том же уровне два различных значения.

Например, процедуры в различных модулях могут иметь одинаковое имя. Таким образом, процедура по имени MySub может быть определена в модулях Mod1 и Mod2. Конфликты не возникают, если каждая процедура вызывается только из других процедур в ее собственном модуле. Однако возможно возникновение ошибки, если MySub вызывается из третьего модуля и отсутствует полная ссылка на определенный модуль, позволяющая различить эти две процедуры MySub.

Большинство конфликтов имен может быть разрешено с помощью предшествующего каждому идентификатору указателя, состоящего из имени модуля и, если нужно, имени проекта. Например:

YourProject.YourModule.YourSub MyProject.MyModule.MyVar

Предшествующая программа вызывает процедуру Sub YourSub и передает переменную MyVar как аргумент. Допускается использование любой комбинации указателей, позволяющей различить одинаковые идентификаторы.

Visual Basic сопоставляет каждую ссылку на идентификатор с "ближайшим" описанием такого идентификатора. Например, если MyID описан как Public в двух модулях проекта (Mod1 и Mod2), то можно указать MyID, описанный в Mod2 без дополнительного указания внутри Mod2, но необходимо точно задать его имя (как Mod2.MyID) для ссылки на него в Mod1. Это справедливо также, если Mod2 находится в другом проекте, который является напрямую адресуемым проектом. Однако если Mod2 находится в косвенно адресуемом проекте, т.е. таком, на который ссылается напрямую адресуемый проект, ссылки на его переменную по имени MyID всегда должны быть полными и содержать имя проекта. Если ссылка на MyID выполняется из внешнего напрямую адресуемого модуля, то она сопоставляется с первым описанием, обнаруженным в следующем порядке:

·        Напрямую адресуемые проекты в том порядке, в котором они появляются в окне диалога Ссылки, вызываемого из меню Сервис.

·        Модули каждого проекта. Следует отметить, что не существует внутреннего порядка для модулей проекта.

Имена объектов главного приложения (например, R1C1 в Microsoft Excel) не могут повторно использоваться на других уровнях области определения.

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

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

Наиболее часто используемые операторы управления VBA следующие:

If-Then-Else Проверяет и меняет ход выполнения программы в зависимости от результата проверки.

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

For-Next  Выполняет повторяющиеся действия заданное число раз

While-Wend  Выполняет повторяющие действия, пока справедливо заданное условие

Do-Loop – Выполняет повторяющиеся действия, пока справедливо заданное условие или до тех пор, пока заданное условие не будет выполнено

For-Each-Next  Выполняет повторяющиеся действия для каждого объекта в семействе или для каждого элемента массива.

Рассматривать подробно не будем, примеры приводятся в lect12.XLS модуль UprOper

If-Then-Else

Данный оператор используется для изменения хода выполнения программы в зависимости от результатов проверки

'===================================================

 

Option Base 1

 

'===================================================

'Пример, демонстрирующий использование оператора If-Then-Else.

'Процедура генерирует случайные числа, выигрыш - число 7.

'===================================================

Sub Lect12uProc15_IfThenElse()

    Dim Num1 As Integer

    Num1 = GetRandomNumber

    If Num1 = 7 Then

        MsgBox "Вы выиграли. Ваше число - " & _

            Num1 & "."

    Else

        MsgBox "Вы проиграли. Ваше число - " & _

            Num1 & "."

    End If

End Sub

 

Function GetRandomNumber()

    GetRandomNumber = Int(10 * Rnd())

End Function

Proc15 начинает свою работу  с вызова функции GetRandomNumber для присвоения  переменной Num1.

Select Case

Инструкция Select Case может служить альтернативой инструкции ElseIf в If...Then...Else при оценке одного выражения, которое имеет несколько возможных значений. В то время как If...Then...Else для каждой инструкции ElseIf оценивает разные выражения, инструкция Select Case оценивает выражение только один раз, в начале управляющей структуры.

В следующем примере Select Case оценивает аргумент performance, который передается в процедуру. Следует отметить, что каждая инструкция Case оценивает несколько значений, диапазон значений или комбинацию значений и операторов сравнения. Необязательная инструкция Case Else выполняется, если Select Case не находит подходящего значения ни в одной из инструкций Case.

 

Function Bonus(performance, salary)

          Select Case performance

                   Case 1

                             Bonus = salary * 0.1

                   Case 2, 3

                             Bonus = salary * 0.09

                   Case 4 To 6

                             Bonus = salary * 0.07

                   Case Is > 8

                             Bonus = 100

                   Case Else

                             Bonus = 0

          End Select

End Function

For...Next

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

Следующая процедура заставляет компьютер подавать звуковой сигнал 50 раз. Инструкция For определяет счетчик х и его начальное и конечное значения. Инструкция Next изменяет счетчик с шагом 1.

 

Sub Beeps()

          For x = 1 To 50

                   Beep

          Next x

End Sub

 

Имеется возможность увеличивать или уменьшать значение счетчика на указанную величину с помощью ключевого слова Step. В следующем примере счетчик j изменяется с шагом 2 при каждом выполнении цикла. По завершении цикла total равняется сумме 2, 4, 6, 8 и 10.

 

Sub TwosTotal()

          For j = 2 To 10 Step 2

                   total = total + j

          Next j

          MsgBox "Сумма равна " & total

End Sub

 

Для уменьшения значения счетчика используется отрицательное значение Step. В этом случае указывается конечное значение, которое должно быть меньше начального значения. В следующем примере счетчик myNum уменьшается на 2 при каждом выполнении цикла. По окончании цикла total равняется сумме 16, 14, 12, 10, 8, 6, 4 и 2.

 

Sub NewTotal()

          For myNum = 16 To 2 Step -2

                   total = total + myNum

          Next myNum

          MsgBox "Сумма равна " & total

End Sub

 

Примечание.   Указание имени счетчика после инструкции Next не обязательно. В предыдущих примерах имя счетчика было указано для облегчения чтения программы.

 

Инструкция Exit For дает возможность завершения инструкции For...Next до того, как счетчик достигнет своего конечного значения. Например, если возникает ошибка, для ее проверки можно использовать инструкцию Exit For в блоке True инструкции If...Then...Else или инструкции Select Case. Если ошибки нет, инструкция If...Then...Else имеет значение False, и выполнение цикла продолжается, как ожидалось.

While-Wend

Выполняет последовательность инструкций, пока заданное условие имеет значение True.

While условие

   [инструкции]

Wend

 

Синтаксис инструкции While...Wend содержит следующие элементы:

Условие «Обязательный».  Числовое выражение или строковое выражение, которое имеет значение True или False.  Если условие имеет значение Null, условие рассматривается как имеющее значение False.

Инструкции  «Необязательный».  Одна или несколько инструкций, выполняемых, пока условие имеет значение True.

Дополнительные сведения

Если условие имеет значение True, выполняются все инструкции до инструкции Wend.  Затем управление возвращается инструкции While и вновь проверяется условие.  Если условие по-прежнему имеет значение True, процесс повторяется.  Если оно не имеет значение True, выполнение возобновляется с инструкции, следующей за инструкцией Wend.

Циклы While...Wend могут иметь любую глубину вложенности.  Каждая инструкция Wend соответствует предшествующей инструкции While.

Do...Loop

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

Повторение инструкций, пока условие имеет значение True

Имеется два способа проверки условия в инструкции Do...Loop с помощью ключевого слова While: условие проверяется до входа в цикл; условие проверяется после хотя бы однократного выполнения цикла.

В следующей процедуре ChkFirstWhile условие проверяется до входа в цикл. Если myNum задать равным 9 вместо 20, инструкции внутри цикла выполняться не будут. В процедуре ChkLastWhile инструкции внутри цикла выполняются только один раз до того как условие примет значение False.

 

Sub ChkFirstWhile()

          counter = 0

          myNum = 20

          Do While myNum > 10

                   myNum = myNum - 1

                   counter = counter + 1

          Loop

          MsgBox "Выполнено " & counter & " итераций цикла."

End Sub

 

Sub ChkLastWhile()

          counter = 0

          myNum = 9

          Do

                   myNum = myNum - 1

                   counter = counter + 1

          Loop While myNum > 10

          MsgBox "В цикле выполнено " & counter & " итераций."

End Sub

 

Имеется два способа проверки условия в инструкции Do...Loop с помощью ключевого слова Until: условие проверяется до входа в цикл (как продемонстрировано в процедуре ChkFirstUntil), или условие проверяется после хотя бы однократного выполнения цикла (как показано в процедуре ChkLastUntil). Итерации продолжаются, пока условие имеет значение False.

 

Sub ChkFirstUntil()

          counter = 0

          myNum = 20

          Do Until myNum = 10

                   myNum = myNum - 1

                   counter = counter + 1

          Loop

          MsgBox "В цикле выполнено " & counter & " итераций."

End Sub

 

Sub ChkLastUntil()

          counter = 0

          myNum = 1

          Do

                   myNum = myNum + 1

                   counter = counter + 1

          Loop Until myNum = 10

          MsgBox "В цикле выполнено " & counter & " итераций."

End Sub

 

Инструкцию Do...Loop можно завершить с помощью инструкции Exit Do. Например, для завершения бесконечного цикла используется инструкция Exit Do в блоке True инструкции If...Then...Else или инструкции Select Case. Если условие имеет значение False, цикл будет выполняться как обычно.

В следующем примере переменной myNum присваивается значение, приводящее к бесконечному циклу. Инструкция If...Then...Else проверяет условие на myNum, а затем завершает инструкцию Do...Loop, предотвращая, таким образом, бесконечный цикл.

 

Sub ExitExample()

          counter = 0

          myNum = 9

          Do Until myNum = 10

                   myNum = myNum - 1

                   counter = counter + 1

                   If myNum < 10 Then Exit Do

          Loop

          MsgBox "В цикле выполнено " & counter & " итераций."

End Sub

 

Примечание.   Для прекращения бесконечного цикла используются клавиши ESC или CTRL+BREAK.

Совет.   Инструкция Do...Loop обеспечивает более структурированный и гибкий способ организации циклов.

For Each...Next

Инструкция For Each...Next повторяет набор инструкций для всех объектов семейства или для всех элементов массива. Visual Basic автоматически задает переменную во время каждого выполнения цикла. Например, в следующей процедуре закрываются все формы, за исключением формы, содержащей текущую процедуру.

 

Sub CloseForms()

          For Each frm In Application.Forms

                   If frm.Caption <> Screen. ActiveForm.Caption Then frm.Close

          Next

End Sub

 

В следующих строках программы выполняется цикл для всех элементов массива, и их значения присваиваются индексной переменной I.

Dim TestArray(10) As Integer, I As Variant

For Each I In TestArray

          TestArray(I) = I

Next I

 

Инструкция For Each...Next используется также для организации циклов по диапазонам ячеек. Следующая процедура выполняет цикл по диапазону A1:D10 на листе Sheet1 и присваивает любому числу, имеющему абсолютное значение меньше 0.01, значение 0 (ноль).

 

Sub RoundToZero()

          For Each myObject in myCollection

                   If Abs(myObject.Value) < 0.01 Then myObject.Value = 0

          Next

End Sub

 

Допускается выход из цикла For Each...Next с помощью инструкции Exit For. Например, если возникает ошибка, для ее проверки можно использовать инструкцию Exit For в блоке True инструкции If...Then...Else или инструкции Select Case. Если ошибки нет, инструкция If...Then...Else имеет значение False, и выполнение цикла продолжается, как ожидалось.

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

 

Sub TestForNumbers()

          For Each myObject In MyCollection

                   If IsNumeric(myObject.Value) = False Then

                             MsgBox "Объект не содержит числового значения."

                             Exit For

                   End If

          Next c

End Sub