Выше уже говорилось, что, используя встроенные объекты, с помощью VBA мы можем управлять приложением. Прежде, чем перейти к изучению встроенных объектов, надо понять, что же такое объект, и как с ним работать. В объектно-ориентированном программировании объект обычно определяется через понятие класс. Класс – это сложный тип, объединяющий данные и код (программы) для их обработки, а объект – это переменная этого типа (экземпляр класса). Примерами объектов могут служить кнопка (объект класса CommandButton), рабочая книга (объект класса Workbook), форма (объект класса UserForm). В литературе обычно опускают слово класс и называют рабочую книгу объектом Workbook, а кнопку – объектом CommandButton.
Каждый объект имеетимя, с помощью которого на него можно сослаться в тексте программы. У элементов управления и формы это значение свойства (Name). В отличие от других свойств, это свойство нельзя изменить во время выполнения программы.
Состояние объекта характеризуется текущим значением его атрибутов. Атрибутами могут быть не только простейшие величины, но и другие объекты. Атрибуты объекта называются свойствами. Свойства элементов управления и формы можно задать в Окне свойств. Для доступа к значению свойства в программе нужно указать имя объекта, точку и имя свойства. Если значение свойства в свою очередь является объектом, то снова поставить точку и указать свойство этого свойства, и т.д. Например,
Selection.Font.Bold = True
Объекты выполняют обработку данных с помощью методов. Метод – это процедура, связанная с объектом. Метод вызывается аналогично свойству. Если нужно, при вызове укажите значения фактических параметров:
Form1.Hide
Form1.Move 20, 20, 200, 100
Событие – это действие, распознаваемое объектом (например, щелчок мышью, нажатие клавиши или переход в другое окно). Возникают события в результате действий пользователя или программы, могут быть инициированы операционной системой. У каждого объекта свой набор событий, созданный разработчиком. Если вы хотите, чтобы при наступлении события ваша программа что–то сделала, напишите процедуру обработки события. Имя процедуры всегда состоит из имени объекта и имени события, между которыми ставится знак подчеркивания. Например, процедура cmdOK_Click будет выполняться, когда пользователь нажмет на кнопку с именем cmdOK, так как в этот момент для нее возникнет событие Click. Для форм процедуры обработки событий имеют имена Form_событие, то есть указывается не имя формы, а слово Form, например, Form_Click. Процедура обработки события размещается в том модуле, в котором используется объект.
Для создания процедуры обработки события перейдите в окно кода нужной формы, например, с помощью кнопки View Code окна проекта. В верхней части окна имеются два списка. В левом списке выберите нужный объект, в правом – событие для этого объекта. Система автоматически создаст заготовку процедуры с именем процедуры в начале и инструкцией End Sub в конце. Допишите в нее нужные инструкции. Если процедура уже существует, она будет показана в окне. Не пишите заготовки процедур обработки событий вручную, так как некоторые события имеют параметры, и вы можете ошибиться. Также имейте в виду, что двойной щелчок по форме или элементу управления приводит к переходу в окно кода формы и созданию процедуры обработки самого типичного события этого объекта (события по умолчанию).
Как мы уже выяснили, объект – это переменная специального типа. Работа с такими переменными в программе похожа на работу с переменными других типов: мы можем их объявлять, присваивать им значения, сравнивать - но в то же время имеет свою специфику. На самом деле объектная переменная хранит ссылку на область памяти, в которой размещена вся информация, относящаяся к объекту. Поэтому любая объектная переменная всегда занимает 4 байта. Это определяется моделью памяти, а не классом. Используя объектную переменную, мы получаем доступ к свойствам, методам и событиям объекта.
Для описания объектной переменной используются обычные инструкции Dim, Public, Private или Static. В качестве типа можно указать Variant, Object или имя класса. Тип Object позволяет создать универсальную ссылку на любой объект. Он используется в том случае, если объектный тип не известен до выполнения процедуры. Например:
Dim O1 ' Описывает O1 с типом Variant
Dim O2 As Object ' Описывает O2 с типом Object
Dim O3 As Font ' Описывает O3 с типом Font
Важно понимать, что описание объектной переменной не означает создание объекта. Чтобы переменная ссылалась на объект, объект нужно создать и присвоить эту ссылку в качестве значения переменной.
Присвоение значения объектной переменной выполняется с помощью инструкции Set:
SetПеременная = Выражение | NewИмяКласса | Nothing
Слева от знака равно может стоять, в том числе, имя свойства, если свойство является объектом. Выражение, стоящее справа, может быть именем другой переменной того же типа, функцией, методом или свойством, которые возвращают объект того же типа. Ключевое слово New используется для создания нового экземпляра объекта указанного класса. Присваивание Nothing (пустая ссылка) разрывает связь переменной с объектом. Когда переменная получает значение Nothing, все системные ресурсы и ресурсы памяти, выделенные для объекта, на который имелась ссылка, освобождаются, если никакие другие переменные на него не ссылаются.
При использовании инструкции Set копия объекта обычно не создается. Значением переменной является ссылка на объект. Следовательно, несколько объектных переменных могут ссылаться на один и тот же объект. Поэтому любые изменения объекта отражаются на всех переменных, которые ссылаются на него.
В качестве примера рассмотрим создание нового рабочего листа (объекта Worksheet). В первом случае лист создается с помощью метода Add, который возвращает ссылку на новый лист, и эту ссылку мы присваиваем переменной newSheet1. Во втором случае лист создается с помощью New. Использовать переменные newSheet1 и newSheet2 мы можем одинаково:
Set newSheet1 = Worksheets.Add
newSheet1.Name = "Отчет"
Set newSheet2 = New Worksheet
newSheet2.Name = "Вычисления"
Для сравнения двух переменных, содержащих ссылки на объекты, нельзя использовать обычную операцию равно. Для этих целей предназначена специальная операция Is. Если переменные содержат ссылки на один объект, результат имеет значение True, в противном случае результат имеет значение False.
В приведенном ниже примере выполняется поиск слова «Образец» в столбце B листа Лист1. В случае обнаружения нужного слова метод Find вернет ссылку на найденную ячейку, в противном случае – пустую ссылку. Результат поиска сохраняется в переменной FC. Так мы можем проверить, чем закончился поиск:
Set FC = Worksheets("Лист1").Columns("B").Find("Образец")
If FC Is Nothing Then
MsgBox "Слово не найдено"
Else
MsgBox "Слово находится в ячейке " & FC.Address
End If
Иногда во время выполнения программы требуется узнать класс объекта, на который ссылается переменная. В этом случае следует использовать операцию TypeOf. Так, например, мы можем проверить тип активного элемента управления в форме (TextBox, PictureBox – это имена классов, свойство ActiveControl хранит ссылку на активный объект):
If TypeOf UserForm1.ActiveControl Is TextBox Then
' Активный элемент - TextBox
ElseIf TypeOf UserForm1.ActiveControl Is PictureBox Then
' Активный элемент - PictureBox
Else
MsgBox “Другой тип данных"
End If
Инструкция With дает возможность выполнить последовательность действий над объектом, не повторяя его имени. Обращение к свойствам и методам объекта внутри инструкции начинается с точки. Инструкция не только облегчает чтение и написание программы за счет уменьшения объема текста, но и позволяет транслятору создать более эффективный код, так как ссылка на объект вычисляется один раз. Синтаксис инструкции:
WithОбъект
[Инструкции]
End With
Пример использования инструкции:
With Worksheets("Лист1").Range("A1:C10")
.Font.Bold = True
.Interior.Color = RGB(255, 255, 0)
End With
В примере форматируются ячейки A1:C10 листа Лист1 (шрифт – полужирный, цвет фона – желтый). Как видим, ссылка на необходимый диапазон указывается один раз, хотя изменяются значения двух свойств объекта.
Отдельные объекты можно объединять в коллекции, подобно тому, как из отдельных элементов можно создать массив. Коллекция – это специальный объект-контейнер, содержащий другие объекты. Создание коллекций, так же как и создание классов, выходит за рамки этого курса, поэтому нам нужно только научиться работать с существующими коллекциями. В приложениях Microsoft используется очень много коллекций, так как они позволяют легко обработать все объекты заданного класса.
Добавление, удаление и другие операции с элементами коллекции реализуются с помощью методов соответствующих классов. Доступ к конкретному элементу коллекции возможен по номеру или по ключу. Нумерация элементов начинается с единицы. При использовании номера нужно указать имя коллекции и в круглых скобках – номер элемента, например, Worksheets(1). Доступ по ключу возможен в том случае, если при добавлении элемента в коллекцию ключ был задан. Ключ – это строка. В коллекции рабочих листов ключом является имя листа, поэтому мы можем обратиться к нужному листу, например, так: Worksheets("Решение"). В данном случае совершенно не важно, какой номер у этого листа, тем более что номер во время выполнения программы может измениться из-за добавления или удаления листов. Количество элементов в коллекции всегда можно узнать с помощью свойства Count. Это свойство доступно только для чтения.
Перебор всех элементов коллекции удобно выполнять с помощью специальной разновидности цикла For Each...Next, которая имеет следующий синтаксис:
For EachПеременнаяInИмяКоллекции
[Инструкции]
[Exit For]
[Инструкции]
Next [Переменная]
Переменная цикла может иметь тип Variant, Object или тип конкретного объекта. Для досрочного выхода их цикла используется инструкция Exit For. Цикл выполняется для каждого элемента коллекции. Имя переменной после Next рекомендуется указывать в тех случаях, когда используются вложенные циклы.
В качестве примера рассмотрим, как подсчитать количество пустых ячеек в выделенном диапазоне. В данном случае объект Selection – это коллекция, состоящая из объектов типа Range: