Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2313

.pdf
Скачиваний:
1
Добавлен:
15.11.2022
Размер:
1.4 Mб
Скачать

Оператор While...Wend

Данный оператор является частным случаем оператора

DO ... Loop.

While условие БлокОператоров

Wend

БлокОператоров выполняется, пока условие истинно. По сути этот оператор является атавизмом, оставленным для совместимости программных продуктов предыдущих версий.

Оператор For Each...Next

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

Итак, представьте, что необходимо вычислить сумму элементов массива, диапазон изменения индексов которого может со временем измениться, даже более того, может измениться его размерность - а программа содержит очень много процедур, в которых входит суммирование массива. Ни один из вышеприведенных циклов использовать нельзя, поскольку, как только изменится размерность, вам придется переписывать эти циклы. Решением является оператор For Each... Next. В этом операторе отсутствует счетчик, а тело цикла выполняется для каждого элемента в массиве.

For Each элемент In группа [блокОператоров1]

[Exit For]

[блокОператоров2] Next [элемент]

Здесь элемент - это переменная, пробегающая значения элементов массива. Под группой мы пока будем понимать только массив. Элемент обязан быть переменой типа variant. А дальше все знакомо. Работа цикла происходит следующим об-

73

разом: блок операторов выполняется, пока переменная элемент не пробежит все элементы массива.

В следующем примере представим, что мы не знаем точного количества магазинов, они могут присоединиться или, наоборот, отказаться от услуг, но (в данном случае) мы хотим подсчитать, сколько всего поступило заявок издательству. Тогда с использованием объявления динамических массивов и оператора For Each.. .Next данная проблема решается без затруднений. Заметьте, что не надо менять цикл, даже если вы исправите размерность массива, например, на shops (25, 2) (заявки на две книги одновременно).

Листинг. Использование цикла For Each. . .Next Sub ex2()

Dim shops() As Integer Dim shop As Variant Dim sum As Integer ReDim shops(1 To 25)

'Инициализация sum = 0

For Each shop In shops sum = sum + shop Next

MsgBox(sum) End Sub

74

5. СТРУКТУРА ПРОГРАММЫ

Мы рассмотрели те элементарные "кирпичики" (операторы и выражения), из которых строится программа.

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

Структура программы VBA представлена на рис. 5.1. Программирование на VBA можно рассматривать, как

управление обьектами приложения. Если упростить иерархическую архитектуру, то в Excel это выглядит так:

Application Workbook

........

Worksheets

......

Cell

.....

То есть главный обьект - приложение. В приложении могут быть несколько книг (Workbook), внутри которых находятся листы (Worksheets) и листы разбиты на ячейки (Cell).

Данная структуризация программ полностью удовлетворяет принципам структурного и модульного программирования.

5.1. Модульное программирование

Модульное программирование - это способ разработки программ, при котором программа разбивается на относительно независимые составные части - программные модули. При этом каждый модуль может разрабатываться, программироваться, транслироваться и тестироваться независимо от других.

75

Приложение

Проект 1

Модуль 1

Declarations

Процедура 1

Процедура 2

Процедура N

Модуль 2

Модуль N1

Проект 2

Проект N2

Рис. 5.1. Структура программы VBA

Все системы программирования в той или иной форме поддерживают понятие модуля. В разных системах програм-

76

мирования модули называются и определяются по-разному: подпрограмма, функция, класс, модуль, компонента и т. д. Как правило, модульная структура допускает вложение модулей или ссылки между модулями (или то и другое), поэтому каждый модуль в отдельности может быть сделан обозримым для программиста. Таким образом, модульное программирование является непосредственной реализацией принципа "разделяй и властвуй" в программировании.

Кроме непосредственной структуризации текста программы на модули в системах программирования навешивается еще множество дополнительных функций: сокращение объема кода, инкрементальная компиляция, ограничение областей действия, раннее (статическое) и позднее (динамическое) связывание, инкапсуляция данных и пр.

5.2. Составляющие программы

Итак, модуль - это часть программы, оформленная в виде, допускающем ее независимую трансляцию. Модуль в свою очередь состоит из двух разделов: раздел объявлений (Declarations) и раздел процедур и функций. В разделе Declarations описываются глобальные переменные, типы, определенные пользователем, и перечисляемые типы. В следующем же разделе описываются процедуры и функции. Процедура - минимальная семантически законченная программная конструкция, допускающая выполнение. В конце концов, просто так операторы не выполняются и не пишутся - они находятся в описании процедур и функций.

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

Существует три уровня видимости и пять способов объявления.

1.Процедура (область видимости - только та процедура,

вкоторой переменная объявлена).

77

Приложение

Проект

Модуль

Процедура

Рис. 5.2. Области видимости переменных

-Оператор Dim объявляет переменную внутри тела процедуры и в любом месте процедуры, но до операторов, использующих ее. Время "жизни" данной переменной - это рамки процедуры, т. е. при входе в данную процедуру под переменную выделяется память и происходит ее инициализация, затем,

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

-Оператор static аналогичен оператору Dim: он объявляет статическую переменную. Разница состоит в том, что при выходе из процедуры у статической переменной память не отбирается, а становится (в силу области видимости) временно недоступной, и соответственно сохраняется ее значение, которым при повторном обращении к процедуре можно воспользоваться.

2. Модуль (область видимости - все процедуры модуля, в котором переменная объявлена).

-Оператор Private объявляет переменную в разделе описаний Declarations (вне процедур модуля)

-Оператор Dim абсолютно аналогичен (в данном случае) оператору Private.

3. Приложение (область видимости - все процедуры всех модулей активного приложения).

-Оператор Public объявляет переменную в разделе опи-

саний Declarations.

78

5.3. Объявление процедур и функций

Процедуры, как и все пользовательские элементы VBA, требуют объявления. Объявление процедуры имеет следующий синтаксис:

[Private I Public I Friend] [Static] Sub имяПроцедуры _ ([списокПараметров])

[блокОператоров 1]

[Exit Sub]

[блокОператоров2]

End Sub

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

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

имяПроцедуры - это идентификатор процедуры, удовлетворяющий всем правилам создания имен.

После имени идут обязательные скобки, но необязательный списокпараметров. Давайте подробнее рассмотрим объявление одного параметра; если их больше, то они разделяются запятой.

[Optional] [ByVal | ByRef] [ParamArray] имяПараметра[()] _ [As типДанных] [= значениеПоУмолчанию]

Ключевое слово Optional означает, что параметр необязателен и его можно опустить при вызове процедуры. По умол-

79

чанию параметр обязателен. Все необязательные параметры должны находится после обязательных. Естественно, что значениеПоУмолчанию - это значение необязательного параметра, если он не будет задан при вызове процедуры. Если в конструкции будет использовано ключевое слово ParamArray, то использование ключевого слова optional невозможно.

В качестве фактических аргументов процедура может получать не только значения констант, но и значения переменных. При передаче переменных в качестве аргументов процедуре может использоваться один из двух способов: ByVal (по значению) и ByRef (по ссылке).

Передача параметров по ссылке и по значению

При объявлении переменной какого-либо типа выделяется область в памяти компьютера, в которой будет храниться значение переменной. Размер этой области, понятно, зависит от типа этой переменной.

Если переменная передается в процедуру по ссылке (т. е. с использованием перед ее именем ключевого слова ByRef), то процедуре будет передан адрес этой переменной в памяти. При этом происходит отождествление формального параметра процедуры и переданного фактического аргумента. Тем самым вызываемая процедура, изменяя значение формального параметра, изменяет значение переменной.

Если же переменная передается по значению (т. е. с использованием перед ее именем ключевого слова ByVal), то компилятор создает временную копию этой переменной, и именно адрес этой переменной-копии передается процедуре. Тем самым вызываемая процедура, изменяя значение формального параметра, изменяет значение переменной-копии (но не самой переменной), которая будет уничтожена после завершения работы процедуры.

По умолчанию в VBA переменные передаются по ссыл-

ке.

80

Ключевое слово ParamArray может появиться только перед последним параметром в списке параметров, указывая, что он является необязательным массивом элементов типа variant.

имяАргумента - это идентификатор, составленный согласно правилам создания имен и представляющий аргумент в теле процедуры. Элемент типДанных - это либо встроенный тип данных, либо тип, определенный пользователем. По умолчанию типДаных является типом Variant.

После описания процедуры идет блокоператоров1 (обычно называемый телом процедуры), в котором могут быть использованы значения аргументов процедуры. Если в ходе выполнения операторов процедуры встречается оператор Exit Sub (выход из процедуры), то выполнение процедуры прекращается и управление передается оператору, следующему за оператором вызова процедуры.

Функция отличается от процедуры тем, что помимо выполнения операторов ею возвращается некоторое значение. Синтаксис описания функции немногим отличается от процедуры:

[Public I Private I Friend] [Static] Function имяфункции__ _ [(списокПараметров)] [As типЗначения] [блокОператоров 1] [имяфункции = Выражение]

[Exit Function]

[блокОператоров2] [имяфункции = Выражение]

End Function

Во-первых, ключевое слово Sub заменено Function. Вовторых, после объявления параметров следует указать тип возвращаемого функцией значения.

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

81

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

И наконец, вместо ключевого слова Exit Sub для выхода из функции используется ключевое слово Exit Function. Давайте на примере структуры книги опишем процедуру инициализации ее содержания, т. е. инициализацию массива content (). Итак, у нас есть аргумент - массив, который передается процедуре initcontent, а процедура инициализирует его посредством использования стандартной функции inputBox. При этом процесс инициализации происходит в бесконечном цикле, каждый раз изменяя размерность массива - так происходит до тех пор, пока пользователь не нажмет кнопку Отмена или не введет пустую строку, что мы проверяем вышеописанным условным оператором if.. .Then.. .Else.

Помимо вышеописанного объявления процедур и функций, в VBA существует особый вид процедур. Это процедуры реакции на событие, вызываемое системой или пользователем (см. главу 7). Например, для документов Word определены со-

бытия open и close, для рабочих книг Excel - Beforesave и BeforeClose, для объектов Пользовательских Классов - Initialize и Terminate; нажатие кнопки диалогового окна тоже является событием и т. д. Пользователь способен сам создать процедуру реакции на подобные события, например попросить выводить сообщение "До свидания, спасибо за работу!" при закрытии документа.

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

Листинг. Процедура реакции на событие

Private Sub Workbook_BeforeClose (Cancel As Boolean)

MsgBox "До свидания, спасибо за работу!"

End Sub

82

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