Поиск…
Синтаксис
Исходный модуль :
[Public] Event [identifier]([argument_list])
Модуль обработчика :
Dim|Private|Public WithEvents [identifier] As [type]
замечания
Событие может быть только
Public
. Модификатор является необязательным, поскольку члены модуля модуля (включая события) по умолчанию неявноPublic
.Переменная
WithEvents
может бытьPrivate
илиPublic
, но неFriend
. Модификатор является обязательным, потому чтоWithEvents
не является ключевым словом, которое объявляет переменную, но является частью ключевого слова модификатора синтаксиса объявления переменной. Следовательно, ключевое словоDim
должно использоваться, если модификатор доступа отсутствует.
Источники и обработчики
Что такое события?
VBA управляется событиями : код VBA запускается в ответ на события, вызванные хост-приложением или хост-документом - понимание событий является основополагающим для понимания VBA.
API часто выставляют объекты, которые вызывают ряд событий в ответ на различные состояния. Например, объект Excel.Application
вызывает событие, когда новая рабочая книга создается, открывается, активируется или закрывается. Или когда рассчитывается рабочий лист. Или непосредственно перед сохранением файла. Или сразу после. Кнопка в форме вызывает событие Click
когда пользователь нажимает на нее, сама пользовательская форма вызывает событие сразу после его активации, а другая перед закрытием.
С точки зрения API, события являются точками расширения : клиентский код может выбрать реализацию кода, который обрабатывает эти события, и выполнять собственный код при каждом запуске этих событий: таким образом вы можете автоматически выполнять свой пользовательский код каждый раз, когда выбор изменяется на любом листе - путем обработки события, которое запускается, когда выбор изменяется на любом рабочем листе.
Объект, который предоставляет события, является источником события . Метод, обрабатывающий событие, является обработчиком .
Обработчики
Модули документов VBA (например, ThisDocument
, ThisWorkbook
, Sheet1
и т. Д.) И модули UserForm
являются модулями классов, которые реализуют специальные интерфейсы, которые выставляют несколько событий . Вы можете просматривать эти интерфейсы в выпадающем списке слева вверху панели кода:
В правом выпадающем списке перечислены элементы интерфейса, выбранные в раскрывающемся списке слева:
VBE автоматически генерирует заглушку обработчика событий, когда элемент выбран в правом списке, или перемещается туда, если обработчик существует.
Вы можете определить переменную WithEvents
с модулем в любом модуле:
Private WithEvents Foo As Workbook
Private WithEvents Bar As Worksheet
Каждое объявление WithEvents
становится доступным для выбора из раскрывающегося списка слева. Когда в правом выпадающем списке выбрано событие, VBE генерирует заглушку обработчика событий, названную после объекта WithEvents
и имя события, соединенного с подчеркиванием:
Private WithEvents Foo As Workbook
Private WithEvents Bar As Worksheet
Private Sub Foo_Open()
End Sub
Private Sub Bar_SelectionChange(ByVal Target As Range)
End Sub
Только типы, которые выставляют хотя бы одно событие, могут использоваться с WithEvents
, а объявлениям WithEvents
нельзя назначить ссылку на месте с ключевым словом New
. Этот код является незаконным:
Private WithEvents Foo As New Workbook 'illegal
Ссылка на объект должна быть Set
явно; в модуле класса, хорошее место для этого часто Class_Initialize
обработчике Class_Initialize
, потому что тогда класс обрабатывает события этого объекта до тех пор, пока его экземпляр существует.
источники
Любой модуль класса (или модуль документа или пользовательская форма) может быть источником события. Используйте ключевое слово Event
для определения сигнатуры для события, в разделе объявлений модуля:
Public Event SomethingHappened(ByVal something As String)
Подпись события определяет, как будет создаваться событие, и как будут выглядеть обработчики событий.
События могут быть подняты только внутри класса, в котором они определены: клиентский код может обрабатывать их только. События поднимаются с RaiseEvent
словом RaiseEvent
; аргументы события приведены в этот момент:
Public Sub DoSomething()
RaiseEvent SomethingHappened("hello")
End Sub
Без кода, обрабатывающего событие SomethingHappened
, выполнение процедуры DoSomething
все равно вызовет событие, но ничего не произойдет. Предполагая, что источником события является приведенный выше код в классе с именем Something
, этот код в ThisWorkbook
будет показывать окно сообщения «привет» всякий раз, когда test.DoSomething
:
Private WithEvents test As Something
Private Sub Workbook_Open()
Set test = New Something
test.DoSomething
End Sub
Private Sub test_SomethingHappened(ByVal bar As String)
'this procedure runs whenever 'test' raises the 'SomethingHappened' event
MsgBox bar
End Sub
Передача данных обратно в источник события
Использование параметров, переданных по ссылке
Событие может определять параметр ByRef
должен быть возвращен вызывающему абоненту:
Public Event BeforeSomething(ByRef cancel As Boolean)
Public Event AfterSomething()
Public Sub DoSomething()
Dim cancel As Boolean
RaiseEvent BeforeSomething(cancel)
If cancel Then Exit Sub
'todo: actually do something
RaiseEvent AfterSomething
End Sub
Если в событии BeforeSomething
есть обработчик, который устанавливает свой параметр cancel
в значение True
, тогда, когда выполнение возвращается из обработчика, cancel
будет True
а AfterSomething
никогда не будет поднята.
Private WithEvents foo As Something
Private Sub foo_BeforeSomething(ByRef cancel As Boolean)
cancel = MsgBox("Cancel?", vbYesNo) = vbYes
End Sub
Private Sub foo_AfterSomething()
MsgBox "Didn't cancel!"
End Sub
Предполагая, что ссылка на объект foo
присваивается где-то, когда запускается foo.DoSomething
, окно сообщения запрашивает, следует ли отменить, а второе поле сообщения говорит «не отменять» только тогда, когда выбрано « Нет» .
Использование изменяемых объектов
Вы также можете передать копию ByVal
объекта ByVal
и позволить обработчикам изменять свойства этого объекта; вызывающий может затем прочитать измененные значения свойств и действовать соответственно.
'class module ReturnBoolean
Option Explicit
Private encapsulated As Boolean
Public Property Get ReturnValue() As Boolean
'Attribute ReturnValue.VB_UserMemId = 0
ReturnValue = encapsulated
End Property
Public Property Let ReturnValue(ByVal value As Boolean)
encapsulated = value
End Property
В сочетании с типом Variant
это можно использовать для создания довольно неочевидных способов вернуть значение вызывающему:
Public Event SomeEvent(ByVal foo As Variant)
Public Sub DoSomething()
Dim result As ReturnBoolean
result = New ReturnBoolean
RaiseEvent SomeEvent(result)
If result Then ' If result.ReturnValue Then
'handler changed the value to True
Else
'handler didn't modify the value
End If
End Sub
Обработчик будет выглядеть так:
Private Sub source_SomeEvent(ByVal foo As Variant) 'foo is actually a ReturnBoolean object
foo = True 'True is actually assigned to foo.ReturnValue, the class' default member
End Sub