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

VBA. Практическое программирование

.pdf
Скачиваний:
0
Добавлен:
12.08.2026
Размер:
666 Кб
Скачать

Основные конструкции языка

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

С развитием объектно-ориентированного программирования появились новые конструкции. К ним относятся и For Each...Next и With...End With.

Конструкция For Each...Next

Как правило однотипные объекты (ячейки, листы рабочей книги, слова текстового документа) объединяются в коллекции. Если возникает необходимость выполнить какие-то одинаковые команды с каждым из объектов в коллекции, то конструкция For Each...Next может в этом помочь. Синтаксис этой конструкции следующий

For Each <элемент> In <группа> [инструкции]

[Exit For] [инструкции] Next [<элемент>]

Вместо <элемент> Вы должны вставить имя переменной и потом внутри конструкции использовать это имя, если хотите указать на объект из коллекции. Вместо <группа> Вы подставляете имя коллекции объектов, которые Вы собираетесь обрабатывать. Познакомьтесь с примером, когда ячейки из диапазона c4:h10 окрашиваются в цвет, номер (индекс) которого равен номеру строки, в которой располагается ячейка. Отметим, что <элемент> обозначается в примере через переменную X и после такого обозначения эта переменная воспринимается как ячейка рабочего листа, обладающая соответствующими свойствами.

Private Sub CommandButton1_Click() Range(''a1:k20'').Clear

For Each X In Range(''c4:h10'') — в этой строке в роли коллекции выступает объект Range, который действительно в свою оче- редь является коллекцией ячеек.

X.Interior.ColorIndex = X.Row — выражение X.Row означает «номер строки, в которой располагается эта ячейка.

Next x End Sub

41

1. Основы VBA

Этот пример находится в файле «Коллекции» (Пример 1)

Конструкция With...End With

Если возникает необходимость изменить сразу несколько свойств у одного и того же объекта, то можно использовать конструкцию With...End With со следующим, достаточно простым синтаксисом

With <объект> [инструкции] End With

Вместо <объект> Вы указываете имя конкретного объекта, свойства которого надо менять. Например With Cells(4,5). При этом в других строчках, где ссылаемся на свойства этого объекта, его имя указывать не нужно

Предлагаем Вашему вниманию пример, где обрабатываются все ячейки из коллекции Range(«c4:h10»). Внутри цикла For Each эти ячейки имеют имя Õ. В переменную z (z = X.Column + X.Row) заносится сумма номеров строки и столбца, в которых находится эта ячейка. Затем, используя конструкцию With ... End With, в эту ячейку записываем z (.Value = z) и изменяем цвет фона ячейки.

Private Sub CommandButton1_Click() Range(''a1:k20'').Clear

For Each X In Range(''c4:h10'') z = X.Column + X.Row

With X

.Interior.ColorIndex = X.Row

.Value = z End With

Next X End Sub

Реализацию этого примера Вы найдете в «Коллекции.xls» (Пример 2)». Вам ткже полезно будет самостоятельно рассмотреть пример 3, где объединены три управляющие конструкции.

Процедуры и функции

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

42

Процедуры и функции

дуры и функции, принадлежащие данному модулю. Так, модулем можно считать блок, принадлежащий рабочему листу книги (каждому листу свой модуль), книге в целом, можно вставить «независимый модуль». Также в VBA в наследство от VB существует очень удобный элемент управления Форма (UserForm). Этот элемент имеет много свойств, схожих со свойствами командной кнопки, надписи и т. д. Кроме того, одно из важных преимуществ этого элемента — возможность располагать на нем другие элементы и таким образом создавать свой интерфейс проекта, независимый от интерфейса приложения. Видимо, по этой причине в редакторе VBA помимо создания модулей и процедур предусмотрено создание форм, и они занимают особое место по сравнению с другими стандартными элементами управления. Формы тоже имеют свои модули. Четкие представления о модуле позволяют понять взаимное размещение процедур и функций по отношению друг к другу и способы их взаимодействия. Это, в свою очередь, позволяет понять, какая процедура может быть вызвана без указания модуля, в котором она находится, какие переменные являются общими для тех или иных частей проекта и так далее.

Мы уже создавали процедуры в самом простом варианте, но теперь рассмотрим случаи, когда процедуры могут быть расположены в самых различных модулях, и нам необходимо определиться, насколько эта процедура будет доступна для других модулей, как должны вести себя параметры внутри процедуры. Кроме того, при создании процедур необходимо обращать внимание на поведение переменных используемых внутри процедуры. В ряде случаев эти переменные нужны только для этой процедуры (внутренние переменные), но в других ситуациях переменные могут понадобиться и для других процедур. Также важно определиться, как будут вести себя внутренние переменные процедуры при ее многократном вызове — либо сохранять предыдущие значения, либо «обнуляться». В обычных ситуациях эти переменные при каждом вызове процедуры равны нулю.

Посмотрите на синтаксис инструкции, которую мы должны использовать при создании процедуры

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

[Exit Sub] [инструкции] End Sub

43

1. Основы VBA

Как видите перед ключевым словом Sub можно добавить слова Private или Public, а также слово Static. Смысл этих элементов представлен в таблице 5.

 

Таблица 5

 

Элементы синтаксиса инструкции Sub

 

 

 

Элемент

 

Описание

 

 

 

Public

 

Необязательный. Указывает, что процедура Sub

 

 

доступна для всех других процедур во всех модулях.

Private

 

Необязательный. Указывает, что процедура Sub

 

 

доступна для других процедур только того модуля,

 

 

в котором она описана.

Static

 

Необязательный. Указывает, что локальные

 

 

переменные процедуры Sub сохраняются в

 

 

промежутках времени между вызовами этой

 

 

процедуры. Атрибут Static не действует на

 

 

переменные, описанные вне процедуры Sub, даже если

 

 

они используются в процедуре.

èìÿ

 

Обязательный. Имя процедуры Sub, удовлетворяющее

 

 

стандартным правилам именования переменных.

Список

 

Необязательный. Список переменных,

Аргументов

 

представляющий аргументы, которые передаются

 

 

в процедуру Sub при ее вызове. Имена переменных

 

 

разделяются запятой.

Инструкции

 

Необязательный. Любая группа инструкций,

 

 

выполняемых в процедуре Sub.

 

 

 

Отдельного внимания требует такой параметр как Список Аргументов. Очень часто процедура работает с какой-либо переменной, числовое значение которой важно для других процедур, и мало того, именно для обработки ряда внешних переменных используется эта процедура. Для удобства программирования при написании процедуры эта переменная может быть обозначена внутри процедуры каким-то своим именем, в то время как в других процедурах эта переменная может иметь другое имя, хотя значение этой переменной будет находиться в определенной области памяти, общей для всех процедур. Так вот, список аргументов позволяет устанавливать правильное соотношение между именами переменных внутри и вне процедуры, чтобы процедуры «понимали», о какой области памяти идет речь. В списке аргументов перечисля-

44

Процедуры и функции

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

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

В упрощенном варианте Список Аргументов формируется следующим образом

[ByVal] имяПеременной [As тип]

Необязательный элемент [ByVal] необходимо использовать в том случае, если данную переменную можно использовать только по значению.

Посмотрите на пример, в котором описывается процедура с двумя внешними переменными (L, W) и предполагается, что при ее вызове значения этих переменных будут заданы. Внутри процедуры будет вычислена площадь прямоугольника, сохраненная в во внутренней переменной Area.

Sub Sq(L, W)

Dim Area As Double Объявляем локальную переменную.

If L = 0 Or W = 0 Then

Если хотя бы один из аргументов равен 0.

Exit Sub то процедура немедленно завершается.

End If

Area = L * W Вычисляется площадь прямоугольника.

Debug. Print Area' Выводится полученное значение в окно отладки.

End Sub

Теперь посмотрим, как можно заставить процедуру работать или, по другому, — вызвать. Напомним, что некоторые процедуры могут быть вызваны с помощью событий на элементах управления или на объектах. Чтобы вызвать процедуру Sub из другой процедуры, следует указать в отдельной строке имя этой процедуры и зна- чения для всех требуемых аргументов. Возможно, также, использование инструкции Call, после которой вставляется имя процедуры, и аргументы должны быть заключены в скобки. При подстановке параметров, которые нужны для работы вызываемой процедуры, следует учитывать, что имена этих параметров во внешней и в вызываемой процедурах могут не совпадать (вместо

45

1. Основы VBA

имен параметров можно подставлять числовые значения); важно соблюдать последовательность перечисления соответствующих параметров.

Так, если нам необходимо вычислить площадь прямоугольника с длиной 50 единиц и шириной 45, то процедура Sq может быть вызвана следующими способами

Sq 50, 45

Èëè

Call Sq(50, 45).

Если значения длины и ширины перед вызовом процедуры хранятся в переменных А и В, то процедуру можно вызвать и так

Sq À, Â

Èëè òàê

Call Sq(À, Â).

Почти такая же инструкция используется для описания функции. Напомним, что отличие функции от процедуры заключается в том, что функция должна передать в программу, вызвавшую ее значение одной переменной, и для этого в коде процедуры должна быть строка, в которой значение этой переменной запоминается под именем функции. Поэтому, при описании функции, после указания ее имени, можно указать тип переменной, которая «пря- чется» под именем этой процедуры.

[Public | Private] [Static] Function имя [(список Аргументов)] [As тип]

[инструкции] [имя = выражение] — строка передачи значения

[Exit Function] [инструкции] [имя = выражение] End Function

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

Function Sq(L, W)

Dim Area As Double Объявляем локальную переменную.

If L = 0 Or W = 0 Then

Если хотя бы один из аргументов равен 0.

Exit Sub то процедура немедленно завершается.

End If

46

Процедуры и функции

Area = L * W Вычисляется площадь прямоугольника.

Sq = Area Результат вычислений передается в имя функции. Debug. Print Area ' Выводится полученное значение в окно от-

ладки.

End Function

Отметим наличие в последнем примере обязательной строки. Sq = Area Возможен другой вариант Sq = L*W. Тогда переменную Area декларировать не нужно.

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

Ploshad = Sq(50,45)

В этом примере функция вычисления площади стоит после знака = и результат ее работы передается переменной Ploshad.

Еще несколько особенностей, которые нужно учитывать при создании процедур и функций. Процедуры Sub, тип которых не указан явно с помощью слов Public или Private, являются общими по умолчанию. Если не используется слово Static, значения локальных переменных не сохраняются между вызовами процедур.

Все выполняемые команды должны содержаться в процедурах. Не допускается определение процедуры Sub внутри другой процедуры Sub, Function или Property.

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

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

В языке VBA содержится большое количество встроенных процедур, которые вызываются таким же образом, например для вы- числения синуса х используем строчку

Y=Cos(x)

47

1. Основы VBA

Описание переменных

Вы помните, что при описании переменных обычно используется инструкция Dim. Для создания переменной на уровне процедуры инструкция описания помещается внутри процедуры. Чтобы создать переменную на уровне модуля, инструкция описания располагается в начале модуля, в разделе описаний (General).

В следующем примере создается переменная sName и задается тип данных String.

Dim sName As String

Когда эта инструкция располагается в процедуре, переменная sName может использоваться только в данной процедуре. Если же такая инструкция находится в разделе (General), то переменная sName доступна для всех процедур данного модуля, но не может использоваться процедурами из других модулей проекта. Чтобы сделать переменную доступной для всех процедур проекта, перед ней надо поставить инструкцию Public, как показано в следующем примере:

Public sName As String

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

Dim inpX As Integer, inpY As Integer, inpZ As Integer

В следующей строке inpX и inpY описываются как Variant; и только inpZ описывается как Integer.

Dim inpX, inpY, inpZ As Integer

Инструкция Public используется для описания общих переменных на уровне модуля.

Public sName As String

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

48

Массивы

Инструкция Private используется для описания «личных» переменных уровня модуля.

Private MyName As String

«Личные» переменные доступны только для процедур одного и того же модуля.

На уровне модуля инструкция Dim эквивалентна инструкции Private, но использование инструкции Private может упростить чтение и отладку программы. Переменные, описанные с помощью инструкции Static вместо инструкции Dim, сохраняют свои значе- ния при выполнении программы.

Инструкция Option Explicit, помещенная в модуль перед всеми процедурами налагает требование явного описания всех переменных этого модуля и при попытке использования неописанного или неверно введенного имени переменной возникает ошибка во время компиляции.

В заключение отметим, что от старых традиций Бейсика VBA сохранил возможность «быстро» объявлять переменные с помощью суффиксов, присоединяемых к именам переменных (см. таблицу 6)

Таблица 6 Суффиксы для различных типов переменных

Òèï

Суффикс

Пример

Òèï

Суффикс

Пример

переменной

переменной

 

 

 

 

 

 

Integer

%

Z%

Double

#

Y#

Long

&

K&

String

$

F$

Single

!

X!

 

 

 

 

 

 

 

 

 

Массивы

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

49

1. Основы VBA

с 30 элементами, вместо того, чтобы описывать 30 отдельных строковых переменных. Элементы массива отличаются друг от друга по номерам или индексам. Каждый элемент массива содержит одно значение. Следующая инструкция описывает массив Family с 30 элементами. По умолчанию индексация массива начинается с нуля, так что верхняя граница массива — 29, а не 30.

Dim Family (29) As String

Также можно в отдельном массиве сохранить значение зарплаты этих сотрудников

Dim Zarp (29) As Long

Можно пойти еще дальше, и в двумерном массиве хранить зарплату за все 12 месяцев. Тогда объявление двумерного массива будет выглядеть так

Dim Zarpgod (29,11) As Long

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

Family (0) = ''Ананасов''

Family (1) = ''Ветров''

Зарплату этих сотрудников сохраним соответственно

Zarp(0) = 25000

Zarp(1) = 28000

Можно запомнить и их зарплату за январь месяц (номер месяца равен 0) в двумерном массиве

Zarpgod (0,0) = 18000

Zarpgod (1,0) =15000

Если нас не устраивает начало нумерации с нуля, то можно описать массив с указаием верхней и нижней границы

Dim Zarpgod (0 To 29, 1 To 12)

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

Sub TotulMass()

Dim K As Integer, J As Integer

50