Buscar..
Sintaxis
Módulo de origen :
[Public] Event [identifier]([argument_list])
Módulo de controlador :
Dim|Private|Public WithEvents [identifier] As [type]
Observaciones
Un evento solo puede ser
Public
. El modificador es opcional porque los miembros del módulo de clase (incluidos los eventos) son implícitamentePublic
de forma predeterminada.Una variable
WithEvents
puede serPrivate
oPublic
, pero noFriend
. El modificador es obligatorio porqueWithEvents
no es una palabra clave que declara una variable, sino una palabra clave modificadora que forma parte de la sintaxis de declaración de la variable. Por lo tanto, la palabra claveDim
debe usarse si no está presente un modificador de acceso.
Fuentes y manejadores
¿Qué son los eventos?
VBA se basa en eventos : el código VBA se ejecuta en respuesta a los eventos generados por la aplicación host o el documento host. La comprensión de los eventos es fundamental para comprender VBA.
Las API a menudo exponen objetos que generan una serie de eventos en respuesta a varios estados. Por ejemplo, un objeto Excel.Application
genera un evento cada vez que se crea, abre, activa o cierra un nuevo libro de trabajo. O cuando se calcula una hoja de cálculo. O justo antes de guardar un archivo. O inmediatamente después. Un botón en un formulario genera un evento Click
cuando el usuario hace clic en él, el formulario del usuario genera un evento justo después de que se activa y otro justo antes de que se cierre.
Desde la perspectiva de la API, los eventos son puntos de extensión : el código del cliente puede elegir implementar un código que maneje estos eventos y ejecutar código personalizado cada vez que se activen: así es como puede ejecutar su código personalizado automáticamente cada vez que la selección cambia en cualquier hoja de trabajo - manejando el evento que se activa cuando la selección cambia en cualquier hoja de cálculo.
Un objeto que expone eventos es un origen de eventos . Un método que maneja un evento es un manejador .
Manipuladores
Los módulos de documentos VBA (por ejemplo, ThisDocument
, ThisWorkbook
, Sheet1
, etc.) y los módulos UserForm
son módulos de clase que implementan interfaces especiales que exponen una serie de eventos . Puede navegar por estas interfaces en el menú desplegable del lado izquierdo en la parte superior del panel de código:
El menú desplegable del lado derecho muestra los miembros de la interfaz seleccionada en el menú desplegable del lado izquierdo:
El VBE genera automáticamente un apéndice de controlador de eventos cuando se selecciona un elemento en la lista del lado derecho, o navega allí si existe el controlador.
Puede definir una variable WithEvents
ámbito de módulo en cualquier módulo:
Private WithEvents Foo As Workbook
Private WithEvents Bar As Worksheet
Cada declaración WithEvents
está disponible para seleccionar desde el menú desplegable del lado izquierdo. Cuando se selecciona un evento en el menú desplegable del lado derecho, el VBE genera un apéndice de controlador de eventos con el nombre del objeto WithEvents
y el nombre del evento, unido con un guión bajo:
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
Solo los tipos que exponen al menos un evento pueden usarse con WithEvents
, y las declaraciones WithEvents
no pueden ser asignadas una referencia en el momento con la palabra clave New
. Este código es ilegal:
Private WithEvents Foo As New Workbook 'illegal
La referencia del objeto se debe Set
explícitamente; en un módulo de clase, un buen lugar para hacerlo es a menudo en el controlador Class_Initialize
, porque entonces la clase maneja los eventos de ese objeto mientras exista su instancia.
Fuentes
Cualquier módulo de clase (o módulo de documento o formulario de usuario) puede ser un origen de evento. Use la palabra clave Event
para definir la firma del evento, en la sección de declaraciones del módulo:
Public Event SomethingHappened(ByVal something As String)
La firma del evento determina cómo se genera el evento y cómo se verán los controladores de eventos.
Los eventos solo se pueden generar dentro de la clase en la que están definidos, el código del cliente solo puede manejarlos . Los eventos se RaiseEvent
con la palabra clave RaiseEvent
; Los argumentos del evento se proporcionan en ese punto:
Public Sub DoSomething()
RaiseEvent SomethingHappened("hello")
End Sub
Sin el código que maneja el evento SomethingHappened
, la ejecución del procedimiento DoSomething
aún DoSomething
el evento, pero no ocurrirá nada. Suponiendo que el origen del evento es el código anterior en una clase llamada Something
, este código en ThisWorkbook
mostraría un cuadro de mensaje que dice "hola" cada vez que se realiza una 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
Pasar datos de nuevo al origen del evento
Usando parámetros pasados por referencia
Un evento puede definir un parámetro ByRef
destinado a ser devuelto al llamante:
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
Si el evento BeforeSomething
tiene un controlador que establece su parámetro de cancel
en True
, entonces, cuando la ejecución vuelva del controlador, la cancel
será True
y AfterSomething
nunca se generará.
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
Suponiendo que la referencia de objeto foo
se asigna en algún lugar, cuando foo.DoSomething
ejecuta, un cuadro de mensaje le foo.DoSomething
si desea cancelar, y un segundo cuadro de mensaje dice "no cancelar" solo cuando se seleccionó No.
Utilizando objetos mutables
También puede pasar una copia de un objeto mutable ByVal
y dejar que los controladores modifiquen las propiedades de ese objeto; la persona que llama puede leer los valores de propiedad modificados y actuar en consecuencia.
'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
Combinado con el tipo Variant
, esto se puede usar para crear formas no obvias de devolver un valor a la persona que llama:
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
El manejador se vería así:
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