События, их обработка. Автомакросы.
Жизнь в мире объектов была бы скучна, если бы не происходили события во внешнем мире, связанном с пользователем и операционной средой. Получая сообщения о событиях, объекты выполняют специальные методы - обработчики событий. Программируя эти методы, разработчик определяет реакцию объекта на события. Стандартные объекты VBA могут реагировать только на заранее фиксированные события. При создании собственных классов в Office 2000 появилась возможность определить для них собственный набор событий, на которые будут реагировать объекты этого класса. Познакомимся с событиями, на которые могут реагировать объекты Document и Application.
События объектов Document и Template:
Объекты Document и Template могут реагировать на три события:
Таблица 1.3. События объектов Document и Template
Событие |
Возникает, когда |
Open |
В коллекцию Documents добавляется существующий документ, и открывается файл, хранящий этот документ. |
New |
Создается новый документ, который добавляется в коллекцию Documents. |
Close |
Закрывается документ, и он удаляется из коллекции Documents. |
Обработчики событий Open и Close находятся в модуле, связанном с документом (This Document). Помещать в проект конкретного документа обработчик события New не стоит (мы же говорим о создании нового документа!), так что место ему в шаблоне, на основе которого создается новый документ.
События объекта Application:
Многие из объектов Word обладают встроенным набором событий. Но среди них есть странная группа объектов, которые обладают событиями, но появляются по умолчанию как объекты без событий. Эти объекты существуют в двух ипостасях, как объекты без событий и объекты с событиями (With Events). Чтобы включить события для таких объектов, необходимо предпринять ряд мер, в частности создать класс объектов With Events и экземпляр этого класса связать с объектом без событий. Такая технология использется и при работе с объектами собственных классов. Эти объекты создаются по умолчанию без событий, но разработчик вправе определить для них собственный набор событий.
Из стандартных объектов Word наиболее известными объектами этой группы являются объекты Application. Когда открывается Word и создается объект Application, по умолчанию он не имеет событий, которые мог бы обрабатывать. Но можно связать с приложением другой объект (Application With Events), реагирующий на события. В Office 97 у этих объектов было всего два события Quit и DocumentChange, возникающие, при попытках пользователя закрыть приложение или переключится с одного документа на другой. В Office 2000 набор событий существенно расширился и теперь их более десяти. Для того чтобы создать обработчик событий объекта Application необходимо:
Создать класс, в который вложен объект Application WithEvents;
Создать в классе обработчики событий этого объекта, следуя обычной технологии.
Создать экземпляр этого класса и связать объект Application WithEvents с объектом Application.
Начнем решение этой задачи с создания нового класса объектов. Этот класс очень прост и содержит лишь одно свойство, задающее объект с событиями. Вот определение этого класса:
Option Explicit
'Класс EventsOfApp
Public WithEvents AppEv As Word.Application
Листинг 1.67.
Как только это свойство определено, в окне списка объектов этого модуля появляется объект AppEv, обладающий событиями, тут же можно выбрать соответствующее событие, создать заготовку и затем наполнить ее содержанием. Я написал несколько простых обработчиков следующих событий объекта AppEv в этом классе. Вот их тексты:
Private Sub AppEv_DocumentOpen(ByVal Doc As Document)
MsgBox ("Hi " & Doc.Name)
End Sub
Private Sub AppEv_DocumentChange()
Const Msg1 = "Вы переключились на работу с новым документом!"
Call MsgBox(Msg1 & vbCrLf & ActiveDocument.Name, vbInformation, "Окно информации!")
End Sub
Private Sub AppEv_DocumentBeforeClose(ByVal Doc As Document, Cancel As Boolean)
MsgBox ("Вы закрываете документ " & Doc.Name)
DocQuit
End Sub
Листинг 1.68.
Первый из этих обработчиков выдает приветствие при открытии документов Word, второй - сообщает о переключении на работу с новым документом, а третий - выдает предупреждающую информацию непосредственно перед закрытием документа.
Чтобы все это заработало, необходимо создать сам объект Application WithEvents и связать его с существующим объектом Application. В стандартном модуле того же документа DocOne, в котором я создал класс EventsOfAp, я определил экземпляр этого класса и написал процедуру OnEvents, осуществляющую связывание. Взгляните на соответствующий текст:
Public App1 As New EventsOfApp
Public Sub OnEvents()
'Определение объекта Word.Application with Events
'Связывание
Set App1.AppEv = Word.Application
'Теперь начинают работать обработчики событий у Word.Application
End Sub
Public Sub DocQuit()
With ActiveDocument
If ExistVar("CounterDoc") Then
MsgBox "Число открытий документа " & .Name & vbCrLf & _
.Variables("CounterDoc"), VBE xclamation, "Число открытий документа!"
Else
MsgBox "У документа " & .Name _
& " нет счетчика числа открытий", VBE xclamation, "Число открытий документа!"
End If
End With
End Sub
Листинг 1.69.
Как только процедура OnEvents будет выполнена, произойдет связывание и с этого момента объект Word.Application будет обладать событиями и реагировать на переключение между документами, открытие и закрытие документов. Конечно, все это будет происходить с момента запуска процедуры OnEvents документа DocOne и до момента его закрытия. Естественно, что при закрытии DocOne прекратит свое существование класс с обработчиками событий и сам объект Application With Events. Следовательно, прекратится реагирование на события и объект Application, продолжающий существовать, вернется в состояние, заданное по умолчанию.
Автомакросы:
Автомакросы (Auto Macros) - это макросы со специально фиксированными именами. Они вызываются при возникновении ряда событий и являются альтернативным способом их обработки. Можно задействовать как обработчики событий, так и макросы, или оба механизма вместе. Вот макросы, автоматически запускаемые при возникновении соответствующего события в Word:
AutoExec - при запуске приложения Word;
AutoNew - при создании нового документа;
AutoOpen - при открытии существующего документа
AutoClose - при закрытии документа;
AutoExit - при выходе из приложения
Как и обработчики, макросы можно поместить непосредственно в документ или шаблон, на основе которого документ создается. Макрос будет выполняться, если он находится в активном документе, или в шаблоне Normal или в шаблоне, на основе которого открыт активный документ.
Давайте напишем макрос AutoOpen и поместим его в наш документ. Макрос будет выполнять действия процедуры OnEvents, связывая объект App1 класса EventsOfApp с текущим приложением, что позволит реагировать на события объекту Application. Текст его прост:
Sub AutoOpen()
'Связывание объекта Application с событиями
Set App1.AppEv = Application
End Sub
Листинг 1.70.
Важно, что это все действительно работает, в чем мы убедились, экспериментируя с нашим тестовым документом.