Программа — это последовательность...



Программа — это последовательность операторов, и все. Пока программы невелики, такой подход вполне работоспособен. Если в программе 10 операторов, то никакой дополнительной структуры не нужно. Но если в про

грамме 10 000 операторов или 10 000 000 операторов (а такие программы есть, и они работают), то без введения дополнительной структуры не обойтись.

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

Данная структуризация программ полностью, удовлетворяет принципам структурного и модульного программирования. В настоящем разделе мы подробно обсудим работу на уровне модуля, о работе с приложениями и проектами будет рассказано в разделе 20.6 "Редактор Visual Basic for Application".

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

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

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

Процедура (область видимости — только та процедура, в которой переменная объявлена).

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

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

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


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

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

  • Оператор Public объявляет переменную в разделе описаний Declarations.

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

[Private | Public | Friend] [Static] Sub имяПроцедуры ([ списокАргументов ]}

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

[Exit Sub]

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

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

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

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

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

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

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

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

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

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

Тем самым вызываемая процедура, изменяя значение формального параметра, изменяет значение переменной.

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

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

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

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

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

[Public | Private | Friend] [Static]

Function имяФункции [(списокАргументов)] [As типЗначения]

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

[имяФункции = Выражение] [Exit Function]

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

[имяФункции = Выражение] End Function

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

Давайте на примере об издательстве и магазинах опишем процедуру инициализации массива заявок. Итак, у нас есть аргумент массива, который передается процедуре, а процедура инициализирует его с помощью стандартной функции inputBox. Для определения верхней и нижней границ массива используются стандартные функции LBound и uBound.

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



Содержание раздела