
2 семестр / vba_2002
.pdf
Public WithEvents AppEvents As Application
Private Sub AppEvents_WorkbookOpen _ (ByVal Wb As Excel.Workbook)
Call UpdateLogFile(Wb) End Sub
Этот код объявляет объект Application, который называется AppEvents и поддерживает обработку событий. Процедура AppEvents_WorkbookOpen вызывается каждый раз при открытии рабочей книги. Эта процедура обработки события вызывает процедуру UpdateLogFile и передает ей аргумент Wb, который представляет открытую рабочую книгу. После этого необходимо добавить модуль VBA, содержащий следующий код.
Sub UpdateLogFile{Wb} On Error Resume Next cxt = Wb.FullName
txt = txt & "," & Date & ",• & Time txt = txt & "," & Application.UserName
Fname = ThisWorkbook.Path & "Mogfile.txt" Open Fname For Append As #1
Write #1, txt Close #1
End Sub
Обратите внимание на объявление переменной типа AppClass (гак называется модуль класса). Вызов процедуры I n i t производится в процедуре Workbook_Open, которая расположена в модуле кода объекта ЭтаКнига. Процедура Workbook_Open выглядит следующим образом.
Private Sub Workbook_Open() Call Init
End Sub
Процедура UpdateLogFile открывает текстовый файл (или создает его, если такого файла не существует) и записывает ключевую информацию об открытой рабочей книге: имя файла, полный путь к нему, дату, время и имя пользователя.
Процедура WorkbookIsOpen вызывает процедуру Init . Таким образом, при открытии рабочей книги процедура I n i t создает новый объект.
Этот пример доступен на Web-узле издательства. Удостоверьтесь, что файл скопирован на жесткийдиск передиспользованием. Текстовый файл записывается втупапку, в которойнаходитсярабочая книга.
Отслеживание событий уровня объекта Application
Для того чтобы "прочувствовать" процесс генерации событий, воспользуйтесь списком событий, которые генерируются в процессе повседневной работы.
На Web-узле издательства содержится рабочая книга, отображающая каждое событие уровня объекта Application, которое происходит в процессе работы. Существует два варианта этой рабочей книги. Вариант для Excel 2000 и более поздних версий представляет события в немодальном диалоговом окне UserForm (рис. 19.8). Вариант для Excel 97 отображает каждое событие в окне сообщения (Excel 97 не поддерживает немодальные диалоговыеокна UserForm).
ЧастьV.Совершенныеметодыпрограммирования |
519 |

Рис. 19.8. Эта рабочая книга использует модуль класса для отслеживания всех событии уровня объекта Application
Рабочая книга содержит модуль с 20-тью определенными процедурами (по одной на каждое событие, поддерживаемое объектом Application). Приведем пример одной из таких процедур:
Private Sub XL_NewWorkbook(ByVal Wb As Excel-Workbook) LogEvent "Создание книги: " & Wb.Name
End Sub
Каждая процедура вызывает процедуру LogEvent и передает ей в качестве аргумента имя события и объект. Ниже приведен код процедуры LogEvent.
Sub LogEvent(txt)
EventNum = EventNuin + 1 With UserForml
With . 1ЫEvents
.AutoSize = False
.Caption = .Caption & vbCrLf & txt
.Width = UserForml.FrameEvents.Width - 20
.AutoSize = True End With
.FrameEvents.ScrollHeight = .lblEvents .Height +• 20
.FrameEvents.ScrollTop = EventNum * 20 End With
End Sub
Процедура LogEvent обновляет диалоговое окно UserForm, изменяя свойство Caption элемента управления Label, который называется lblEvents. Кроме того, процедура изменяет значения свойств ScrollHeight и ScrollTop элемента управления Frame, называющегося FrameEvents. Элемент управления Label расположен внутри элемента управления Frame.
События объекта UserForm
Объект UserForm поддерживает достаточно большое количество событий, а каждый элемент управления, размещенный в пользовательском диалоговом окне, поддерживает собственный набор событий. В табл. 19.5 перечислены события объекта UserForm, которые можно перехватывать с помощью VBA.
520 |
Глава 19. КонцепциясобытийExcel |

Таблица 19.5. События, поддерживаемые объектом UserForm
Событие |
Действие, которое приводит к возникновению события |
A c t i v a te |
Активизация диалогового окна |
Addcontroi |
Добавление элемента управления на этапе выполнения |
BeforeDragOver |
Операция перетаскивания в процессе выполнения; указатель мыши расположен |
|
над диалоговым окном |
BeforeDropOrPaste Пользователь собирается вставить или отпустить данные (т.е. момент непо- |
|
|
средственного отпускания кнопки мыши) |
click |
Щелчок мышью в тот момент, когда указатель находится над диалоговым окном |
Dblclick |
Двойной щелчок мышью, когда указатель находится над диалоговым окном |
D e a c t i v a t e |
Деактивизация диалогового окна |
Б г г о г |
Элемент управления вызывает ошибку, но он не может сообщить информацию |
|
об ошибке вызывающей программе |
initialize |
Загрузка в память диалогового окна |
KeyDown |
Нажатие клавиши |
Keypress |
Нажатие пользователем любой клавиши, приводящей к вводу символа |
KeyUp |
Отпускание клавиши |
Layout |
Изменение размера диалогового окна |
MouseDown |
Нажатие кнопки мыши |
MouseMove |
Перемещение указателя мыши |
Mouseup |
Отпускание кнопки мыши |
Queryclose |
Происходит перед тем, как диалоговое окно закрывается |
Removecontrol |
Элемент управления удаляется из диалогового окна на этапе выполнения |
Resize |
Диалоговое окно изменяет размеры |
s c r o l l |
Диалоговое окно прокручивается |
Terminate |
Диалоговое окно прекращает свою работу |
zoom |
Диалоговое окно изменило свой масштаб |
Ряд примеров из глав 13-15 демонстрирует обработку событий для пользовательских диалоговых окон и расположенных в них элементов управления.
События, не связанные с конкретными объектами
События, которые рассматривались ранее, были связаны с конкретными объектами (Application, Workbook, Sheet и т.д.). В этом разделе будут описаны дополнительные события, которые не связаны с определенными объектами: OnTime и OnKey. Доступ к ним осуществляется с помощью методов объекта Application.
ЧастьV.Совершенныеметодыпрограммирования |
121 |

В отличие от других событий, которые рассматриваются в этой главе, события ОпКеу и OnTime программируются с помощью кода, расположенного в модуле VBA общего назначения.
Событие OnTime
Событие OnTime происходит в определенное время суток. Следующий пример демонстрирует обработку событий Excel таким образом, что ровно в 15:00 отображается окно сообщения и раздается звуковой сигнал.
Sub SetAlarm{ )
Application.OnTime TimeValue("15:00:00 " ) , "DisplayAlarm" End Sub
Sub DisplayAlarm()
Beep
MsgBox "Просыпайся. Время пить кофе!"
End Sub
В представленном примере процедура S e tAl arm использует метод OnTime объекта A p p l i c a t i o n для настройки события OnTime. Этот метод принимает два аргумента: время (в данном случае это 3:00 p.m. или 15:00) и имя процедуры, которая будет запушена в указанное время (в приводимом примере используется процедура DisplayAlarm) . После выполнения процедуры S e t A l a r m процедура D i s p l a y A l a r m будет вызвана в 15:00, что приведет к отображению окна сообщения, показанного на рис. 19.9.
Рис.19.9.Этоотосообщения отображаетсявопределенное времясуток
Если необходимо запланировать событие относительно текущего времени суток (например, через 20 минут), то воспользуйтесь следующим оператором:
Application.OnTime Now + TimeValue("00:20:00"), "DisplayAlarm"
Метод OnTime можно также использовать, если вы планируете вызов процедуры на определенную дату. Представленный далее оператор запустит процедуру D i s p l a y A l a r m 1 апреля 2002 года в 12:01,
Application.OnTime DateSerial{2002, 4, 1) + _
TimeValue ("00:00:01lt)J "DisplayAlarm"
Метод OnTime поддерживает два дополнительных аргумента. Если вы планируете использовать этот метод, то обратитесь к справочному руководству для получения более полной информации.
Пример аналоговых часов, приводимый в главе 18. использует событие OnTime для запуска процедуры каждую секунду.
522 |
Глава 19. Концепция событий Excel |

Событие ОпКеу
Впроцессе работы Excel постоянно отслеживает нажимаемые пользователем клавиши. Поэтому вы можете настроить клавишу или комбинацию клавиш, которые при нажатии запустят определенную процедуру.
Вследующем примере используется метод OnKey для настройки события OnKey. В данном случае переназначается значение клавиш <PgUp> и <PgDn>. После выполнения процедуры Setup_OnKey нажатие клавиши <PgDn> приведет к запуску процедуры PgDn_Sub, а нажатие клавиши <PgUp> — процедуры PgUp_Sub. В итоге проведенных изменений нажатие клавиши <PgDn> вызывает перемещение курсора на одну строку вниз, а клавиши <PgUp> — на одну строку вверх.
Sub Setup_OnKey()
Application.OnKey " {PgDn} ", "PgDn__Sub"
Application.OnKey "{PgUp}", "PgUp_Sub"
End Sub
Sub PgDn_Sub()
On Error Resume Next
ActiveCell.Offset(1, 0).Activate
End Sub
Sub PgUp_Sub{)
On Error Resume Next ActiveCell.Offset(-1, 0).Activate
End Sub
Обратите внимание на то, что коды клавиш заключены в фигурные скобки, а не в кавычки. Для получения полного списка кодов клавиатуры необходимо обратиться х справочному руководству. Для поиска разделов укажите ключевое слово OnKey.
В предыдущих примерах использовался оператор On E r r o r Resume Next, который позволял игнорировать все возникающие ошибки. Например, если активная ячейка находится в первой строке, то перемещение на одну строку вверх приводит к возникновению ошибки. Кроме того, если активным является лист диаграммы, то возникнет ошибка, так как на листе диаграммы не существует такого понятия, как активная ячейка.
Запустив следующую процедуру можно отменить событие ОпКеу и вернуть клавишам их обычную функциональность.
Sub Cancel_OnKey() Application.ОпКеу "{PgDn}" Application.ОпКеу "{PgUp}"
End Sub
Использование пустой строки в качестве второго аргумента метода ОпКеу не приводит к отмене текущего события ОпКеу. Вместо этого Excel игнорирует нажатие указанных клавиш и не выполняет вообще никаких действий при их нажатии. Например, приведенный ниже оператор сообщает Excel, что необходимо игнорировать нажатие комбинации клавиш <Alt+F4> (символ процента представляет клавишу <Alt>):
Application.ОпКеу "%{F4}", " "
Несмотря на то, что событие ОпКеу можно использовать с целью назначения определенной комбинации клавиш для запуска макроса, вы также можете воспользоваться диалоговым окном Параметры макроса. Для получения дополнительной информации по этому вопросу обратитесь к главе 9.
Часть V. Совершенные методыпрограммирования |
523 |
Резюме
Вданной главе были рассмотрены методы создания кода, который выполняется при возникновении определенного события.
Вследуюшей главе описываются средства VBA, используемые в Excel для управления другими приложениями.
524 |
Глава 19. Концепция событий Excel |

Взаимодействие с другими приложениями
На |
самых ранних этапах использований персональных |
|
компьютеров взаимодействие между приложениями |
практиковалось очень редко, До появления операционных систем с поддержкой многозадачности взаимодействие между приложениями ограничивалось импортом файлов. Даже копирование информации и вставка ее в другое приложение (то, что теперь доступно любому пользователю) ранее считалось невозможным.
В настоящее время большая часть программного обеспечения разрабатывается с поддержкой минимальных средств взаимодействия приложений. Многие приложения Windows поддерживают буфер обмена, используемый в операциях копирования и вставки данных между приложениями. Большинство программных продуктов для Windows поддерживают технологию DDE (Dynamic Data Exchange — Динамический обмен данными), а более новые продукты — и автоматизацию. В данной главе будут рассмотрены способы, с помощью которых приложения Excel могут взаимодействовать с другими приложениями. Кроме тою, вы будете иметь возможность ознакомиться с полезными примерами.
Запуск другого приложения
Иногда необходимо запустить другое приложение из Excel. Например, можно запустить программу установки соединения или лаже пакетный файл DOS. Разработчик приложения также в состоянии облегчить пользователю доступ к папке Панель управления.
Функция VBA s h e l l упрощает процесс запуска других приложений. В листинге 20.1 представлена процедура, которая запускает приложение Windows Character Map (Таблица символов), позволяющее пользователю ввести специальный символ.

Листинг 20.1. Запуск приложения Windo
Sub RunCharMapO |
|
On Error Resume Wext |
|
Program = "Charmap.exe" |
|
TaskID = Shell(Program, 1) |
|
If Err <> 0 Then |
|
MsgBox "Нельзя запустить |
& Program, vbCritical, "Ошибка" |
End If |
|
End Sub |
|
Приложение, которое запускает эта процедура, показано на рис. 20.1.
Если используется Excel 2002, то программа Windows Character Map (Таблица символов) вам больше не потребуется, так как она дублируется командой Excel Вставка^Символ.
Рис. 20.1. Запуск программы Windows Character Map(Таблицасимволов,1вExcel
Функция S h e l l возвращает номер идентификатора приложения. Этот номер можно использовать позднее для активизации задачи. Второй аргумент функции S h e l l определяет способ отображения приложения (для окна нормального размера с последующей активизацией используется аргумент 1).
Если вызов функции S h e l l завершился неудачно, то будет создано сообщение об ошибке. Таким образом, эта процедура использует оператор On E r r o r для отображения сообщения, если файл нельзя найти или произошла другая ошибке.
Важно понимать, что код VBA продолжает свою работу после запуска приложения, загруженного с помощью функции S h e l l . Другими словами, функция S h e l l запускает приложения асинхронно. Если в процедуре после вызова функции S h e l l находятся другие инструкции, то они выполняются одновременно с запушенной программой. Если инструкции требуют вмешательства пользователя (например, при отображении окна сообщения), то строка заголовка Excel будет мигать, пока активно другое приложение.
В некоторых случаях может понадобиться запустить приложение с помощью функции S h e l l , но при этом код VBA должен прекратить выполняться, пока запущенное приложение не создаст файл, который будет использовав далее в коде VBA. Несмотря на то, что выполнение кода приостановить невозможно, вы вправе создать цикл, который, кроме отслеживания
Глава20.Взаимодействиесдругимиприложениями

состояния запушенного приложения, не выполняет никаких функций. В листинге 20.2 приведен пример окна сообщения, которое отображается на экране тогда, когда приложение, запущенное с помощью функции Shell, завершает свою работу.
'Листинг 20.2. Ожидание завершения работы приложения
Declare Function OpenProcess Lib "kernel32" _ (ByVal dwDesiredAccess As Long, _
ByVal blnheritHandle As Long, _ ByVal dwProcessld As Long) As Long
Declare Function GetExitCodeProcess Lib "kerne232" _ iByVal hProcess As Long, _
ipExitCode As Long) A3 Long
Sub RunCharMap2()
Dim TaskID As Long
Dim hProc As Long
Dim lExitCode As Long
ACCESS_TYPE = &H400
STILL_ACTIVE = &H103
Program = "Charmap.exe"
On Error Resume Next
1 Определение оболочки TaskID = Shell(Program, 1)
'Обработка задачи
hProc = OpenProcess {ACCESS__TYPE, False, TaskID)
|
If Err <? 0 Then |
|
|
|
MsgBox "Нельзя запустить |
& Program, vbCritical, "Ошибка" |
|
|
Exit Sub |
|
|
|
End If |
|
|
|
DO 'Непрерывный цикл |
|
|
|
Проверка процесса |
|
|
|
GetEacitCodeProcesa |
hProc, |
lExitCode |
|
Разрешить обработку события |
||
|
DoEvents |
|
|
|
Loop While lExitCode = |
STILL_ACTIVE |
|
1 |
Задача завершена, отображение |
сообщения |
|
|
MsgBox Program & " завершила свою работу" |
||
End Sub |
|
|
После запуска приложения данная процедура будет постоянно вызывать функцию GetExitCodeProcess а конструкции Do Loop. В цикле проверяется значение переменной lExitCode. Когда программа завершает свою работу, lExitCode изменяет свое значение, цикл завершается, и код VBA продолжает функционировать.
Оба примерадоступны на Web-уэле издательства.
Часть V. Совершенные методы программирования |
527 |

Большинство версий Windows предоставляют разработчикам команду S t a r t , которая также может использоваться в качестве аргумента функции S h e l l . Команда Start не доступна только в Windows NT. Она представлена строковым значением, которое приводит к запуску приложения Windows из командной строки DOS. Использование команды S t a r t заключается в указании имени файла документа (а не исполняемого файла). В результате запускается программа, которая связана с расширением файла необходимого документа. Например, следующие операторы запускают установленный в системе Web-броузер (который отображает файлы с расширением . htm) и загружают документ HTML — homepage. htm.
WebPage = "c:\web\homepage.htm" Shell "Start " & WebPage
Вы также можете указать адрес почтового ящика для запуска почтового клиента, используемого по умолчанию:
Email = "mailto:bgates@microsoft.com" Shell " S t a r t " & Email
Если необходимо обеспечить подобную функцию в Windows NT (или в другой версии Windows, которая не поддерживает команду Start), то воспользуйтесь функцией Windows API ShellExecute . Ниже представлено объявление этой функции API (данный код необходимо разместить в начале модуля VBA).
Private Declare Function ShellExecute Lib "shell32.dll" _ Alias "ShellExecuteA" (ByVal hWnd As Long, _
ByVal lpoperation As String, ByVal lpFile As String, _ ByVal lpParameters As String, ByVal ipDirectory As String, _ ByVal nShowCmd As Long) Aa Long
Следующая процедура демонстрирует вызов функции ShellExecute .
Sub OpenFile()
File = "http://www.microsoft.com"
Call ShellExecute(O&, vbNullString, File, _ vbNullString, vbNullString, vbNonnalFocus)
End Sub
В качестве пути может использоваться URL или имя файла на локальном диске. Например, можно использовать эту функцию для открытия графического файла (JPG или BMP) с помощью программы просмотра графических изображений по умолчанию.
Если приложение, которое необходимо запустить, разработано компанией Microsoft, то воспользуйтесь методом ActivateMicrosoftApp объекта Application. Например,следующаяпроцедураприведеткзапускутекстовогопроцессораWord.
Sub StartWordU
Application.ActivateMicrosoftApp xlMicrosoftWord End Sub
Если Word уже запущен к моменту вызова этой процедуры, то он активизируется. В число других констант, поддерживаемых этим методом, входят: xlMicrosoftPowerPoint, xlMicrosoftMail, xlMicrosoftAccess, xlMicrosoftFoxPro, xlMicrosoftProject И xlMicrosoftSchedulePlus.
Активизация другого приложения
Остерегайтесь потенциальной проблемы: может оказаться, что приложение уже работает в момент использования функции S h e l l для его запуска. Это приведет к запуску нового экземпляра указанного приложения. Вам потребуется активизировать уже работающий экземпляр программы, а не создавать новый.
528 |
Глава 20, Взаимодействие с другими приложениями |