Поиск…


Синтаксис

  • Исходный модуль : [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 являются модулями классов, которые реализуют специальные интерфейсы, которые выставляют несколько событий . Вы можете просматривать эти интерфейсы в выпадающем списке слева вверху панели кода:

Модуль ThisWorkbook реализует события Workbook

В правом выпадающем списке перечислены элементы интерфейса, выбранные в раскрывающемся списке слева:

Модули рабочего листа могут обрабатывать события Worksheet

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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow