Ereignisse: Unterschied zwischen den Versionen

Aus VBA-wiki
Zur Navigation springen Zur Suche springen
(Die Seite wurde neu angelegt: „== Auto-Makros == Auto-Makros werden beim Starten bzw. beim Beenden der Anwendung und / oder beim Öffnen bzw. beim Schließen der Datei, welche das Auto-Makr…“)
 
Keine Bearbeitungszusammenfassung
Zeile 5: Zeile 5:
=== Word ===
=== Word ===


{| class="wikitable"
{| class="wikitable"  
! style="text-align:left;" | Name
! style="text-align:left;" | Name  
! style="text-align:left;" | Beschreibung
! style="text-align:left;" | Beschreibung  
! style="text-align:left;" | Anwendungsbereich
! style="text-align:left;" | Anwendungsbereich
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| AutoNew
| AutoNew
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn  
* von dieser Vorlage ein neues Dokument erzeugt wird
* von dieser Vorlage ein neues Dokument erzeugt wird
| Vorlagen
| Vorlagen
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| AutoOpen
| AutoOpen
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn  
* dieses Dokument
* dieses Dokument  
* diese Vorlage geöffnet wird
* diese Vorlage geöffnet wird
| Vorlagen<br>Dokumente
| Vorlagen<br>Dokumente
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| AutoClose
| AutoClose
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn  
* dieses Dokument
* dieses Dokument  
* diese Vorlage geschlossen wird
* diese Vorlage geschlossen wird
| Vorlagen<br>Dokumente
| Vorlagen<br>Dokumente
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| AutoExec
| AutoExec
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn  
* Word gestartet bzw.
* Word gestartet bzw.  
* das Add-In geladen wird
* das Add-In geladen wird
| Ausschließlich Add-Ins und Normal.dot(m)
| Ausschließlich Add-Ins und Normal.dot(m)
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| AutoExit
| AutoExit
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn  
* Word beendet bzw.
* Word beendet bzw.  
* das Add-In entladen wird
* das Add-In entladen wird
| Ausschließlich Add-Ins und Normal.dot(m)  
| Ausschließlich Add-Ins und Normal.dot(m)
|}
|}


=== Excel ===
=== Excel ===


{| class="wikitable"
{| class="wikitable"
! style="text-align:left;" | Name
! style="text-align:left;" | Name  
! style="text-align:left;" | Beschreibung
! style="text-align:left;" | Beschreibung  
! style="text-align:left;" | Anwendungsbereich
! style="text-align:left;" | Anwendungsbereich
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| Auto_Open
| Auto_Open
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn  
* diese Arbeitsmappe / diese Vorlage geöffnet wird
* diese Arbeitsmappe / diese Vorlage geöffnet wird  
* dieses Add-In geladen bzw. Excel gestartet wird
* dieses Add-In geladen bzw. Excel gestartet wird
| Vorlagen<br>Arbeitsmappen<br>Add-Ins
| Vorlagen<br>Arbeitsmappen<br>Add-Ins
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| Auto_Close
| Auto_Close
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn  
* diese Arbeitsmappe / diese Vorlage geschlossen wird
* diese Arbeitsmappe / diese Vorlage geschlossen wird  
* dieses Add-In entladen bzw. Excel beendet wird
* dieses Add-In entladen bzw. Excel beendet wird
| Vorlagen<br>Arbeitsmappen<br>Add-Ins  
| Vorlagen<br>Arbeitsmappen<br>Add-Ins
|}
|}


=== PowerPoint ===
=== PowerPoint ===


In PowerPoint stehen die Auto-Makros ausschließlich in Add-Ins zur Verfügung. Wenn Sie auch in einer Präsentation einen Weg benötigen, um beim Starten / Laden etwas auszuführen (um zum Beispiel auf Ereignisse zuzugreifen), können Sie (ab PowerPoint 2007) alternativ ein (leeres) Ribbon erzeugen und dessen 'onLoad'-Callback einsetzen.
In PowerPoint stehen die Auto-Makros ausschließlich in Add-Ins zur Verfügung. Wenn Sie auch in einer Präsentation einen Weg benötigen, um beim Starten / Laden etwas auszuführen (um zum Beispiel auf Ereignisse zuzugreifen), können Sie (ab PowerPoint 2007) alternativ ein (leeres) Ribbon erzeugen und dessen 'onLoad'-Callback einsetzen.
{| class="wikitable"
{| class="wikitable"
! style="text-align:left;" | Name
! style="text-align:left;" | Name  
! style="text-align:left;" | Beschreibung
! style="text-align:left;" | Beschreibung  
! style="text-align:left;" | Anwendungsbereich
! style="text-align:left;" | Anwendungsbereich
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| Auto_Open
| Auto_Open
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn  
* dieses Add-In geladen bzw. PowerPoint gestartet wird
* dieses Add-In geladen bzw. PowerPoint gestartet wird
| Ausschließlich in Add-Ins
| Ausschließlich in Add-Ins
|- style="vertical-align:top;"
|- style="vertical-align:top;"
| Auto_Close
| Auto_Close
| Wird ausgeführt, wenn
| Wird ausgeführt, wenn
* dieses Add-In entladen bzw. PowerPoint beendet wird
* dieses Add-In entladen bzw. PowerPoint beendet wird
| Ausschließlich in Add-Ins  
| Ausschließlich in Add-Ins
|}
|}


Zeile 87: Zeile 86:


=== Ereignisse des Menübandes ===
=== Ereignisse des Menübandes ===


== Dokument- (Präsentations- bzw. Arbeitsmappen-) Ereignisse ==
== Dokument- (Präsentations- bzw. Arbeitsmappen-) Ereignisse ==
Zeile 94: Zeile 91:
== Anwendungsereignisse ==
== Anwendungsereignisse ==


Die Anwendungsereignisse werden von der entsprechenden Office-Anwendung zur Verfügung gestellt und können wie hier beschrieben mithilfe einer Ereignisklasse abgerufen werden. Sie umfassen typischerweise Ereignisse wie das Öffnen, Drucken, Speichern von Dateien und reagieren auf Benutzerinteraktion wie das Ändern der Auswahl, das Wechseln zu einer anderen offenen Datei etc.
Die Anwendungsereignisse werden von der entsprechenden Office-Anwendung zur Verfügung gestellt und können wie hier beschrieben mithilfe einer Ereignisklasse abgerufen werden.
 
Sie umfassen typischerweise Ereignisse wie das Öffnen, Drucken, Speichern von Dateien und reagieren auf Benutzerinteraktion wie das Ändern der Auswahl, das Wechseln zu einer anderen offenen Datei etc.


==== Ereignisklasse ====
==== Ereignisklasse ====


1. Deklarieren Sie eine Objektvariable, welche die Anwendung entgegennehmen soll, deren Ereignisse Sie empfangen möchten. Beachten Sie dabei das Schlüsselwort '''WithEvents''': Private '''WithEvents''' myEvents As Application 2. Initialisieren Sie diese Variable bei der Initialisierung der Klasse. Private Sub Class_Initialize() Set myEvents = Application End Sub 3. Nun stehen Ihnen die Anwendungs-Ereignisse zur Verfügung:
1. Deklarieren Sie eine Objektvariable, welche die Anwendung entgegennehmen soll, deren Ereignisse Sie empfangen möchten. Beachten Sie dabei das Schlüsselwort '''WithEvents''':
 
Private '''WithEvents''' myEvents As Application
 
2. Initialisieren Sie diese Variable bei der Initialisierung der Klasse.
 
Private Sub Class_Initialize()
   
    Set myEvents = Application
End Sub
 
3. Nun stehen Ihnen die Anwendungs-Ereignisse zur Verfügung:  
* Setzen Sie die Auswahl 'Objekt' auf 'myEvents'
* Setzen Sie die Auswahl 'Objekt' auf 'myEvents'
* Wählen Sie in der Liste 'Prozedur' das gewünschte Ereignis '''Bitte beachten:''' Verwenden Sie immer die Prozedur-Liste, um ein neues Ereignis hinzuzufügen, weil viele Ereignisse Übergabeparameter verwenden.
* Wählen Sie in der Liste 'Prozedur' das gewünschte Ereignis
 
'''Bitte beachten:''' Verwenden Sie immer die Prozedur-Liste, um ein neues Ereignis hinzuzufügen, weil viele Ereignisse Übergabeparameter verwenden.


==== Ereignisprozedur in einem eigenen Modul ====
==== Ereignisprozedur in einem eigenen Modul ====


1. Erstellen Sie ein Modul, welches die Ereignisklasse ansprechen soll. 2. Deklarieren Sie eine Objektvariable, welche die Ereignisklasse entgegennimmt. Da der Zugriff auf die Ereignisse permanent sein soll, verwenden Sie eine Modulvariable: Private myEvents As clsEvents 3. Erstellen Sie eine Prozedur, welche die Ereignisklasse instanziiert. Hierfür eignet sich das passende [[#Auto-Makros|Auto-Makro]], welches beim Starten bzw. Öffnen ausgeführt wird. Public Sub Auto_Open() Set myEvents = New clsEventsExcel End Sub
1. Erstellen Sie ein Modul, welches die Ereignisklasse ansprechen soll.
 
2. Deklarieren Sie eine Objektvariable, welche die Ereignisklasse entgegennimmt. Da der Zugriff auf die Ereignisse permanent sein soll, verwenden Sie eine Modulvariable:
 
Private myEvents As clsEvents
 
3. Erstellen Sie eine Prozedur, welche die Ereignisklasse instanziiert. Hierfür eignet sich das passende [[#Auto-Makros|Auto-Makro]], welches beim Starten bzw. Öffnen ausgeführt wird.
 
Public Sub Auto_Open()
   
    Set myEvents = New clsEventsExcel
End Sub


==== Wichtige Hinweise ====
==== Wichtige Hinweise ====
Zeile 113: Zeile 136:
== Eigene Ereignisse ==
== Eigene Ereignisse ==


Wenn Sie eine auf mehrere Projekte verteilte Lösung entwickeln, können Sie eigene Ereignisse auslösen und entsprechend darauf reagieren. Sie können eigene Ereignisse zwar auch innerhalb eines einzelnen Projektes verwenden, hier würde der Nutzen jedoch nicht den Aufwand rechtfertigen, weil nach der Abarbeitung eines Schrittes der nächste Schritt direkt aufgerufen werden kann. '''Szenario''' Sie verwenden in Ihren Lösungen eine gemeinsame ToolBox, welche all jene Hilfefunktionen enthält, die für alle Lösungen relevant sind. Für die Kundenanpassungen verwenden Sie ein eigenes Add-In, welches die kundenspezifische Funktionalitäten enthält. Das Kundenmodul hat eine Referenz auf die ToolBox, damit Sie auf dessen Hilfsfunktionen zugreifen können. Eine Aufgabe Ihrer Lösung besteht darin, eine neue Datei zu erstellen. Die Aufgabe wird größtenteils von der ToolBox erfüllt, aber im Anschluss möchten Sie die Möglichkeit haben, zusätzliche kundenspezifische Schritte auszuführen. Nach der Erstellung der Datei und den generellen Schritten soll also die ToolBox dem Kundenmodul mitteilen, dass eine neue Datei erstellt und von der ToolBox vorbereitet worden ist.
Wenn Sie eine auf mehrere Projekte verteilte Lösung entwickeln, können Sie eigene Ereignisse auslösen und entsprechend darauf reagieren. Sie können eigene Ereignisse zwar auch innerhalb eines einzelnen Projektes verwenden, hier würde der Nutzen jedoch nicht den Aufwand rechtfertigen, weil nach der Abarbeitung eines Schrittes der nächste Schritt direkt aufgerufen werden kann.  
 
'''Szenario'''
 
Sie verwenden in Ihren Lösungen eine gemeinsame ToolBox, welche all jene Hilfefunktionen enthält, die für alle Lösungen relevant sind. Für die Kundenanpassungen verwenden Sie ein eigenes Add-In, welches die kundenspezifische Funktionalitäten enthält. Das Kundenmodul hat eine Referenz auf die ToolBox, damit Sie auf dessen Hilfsfunktionen zugreifen können.
 
Eine Aufgabe Ihrer Lösung besteht darin, eine neue Datei zu erstellen. Die Aufgabe wird größtenteils von der ToolBox erfüllt, aber im Anschluss möchten Sie die Möglichkeit haben, zusätzliche kundenspezifische Schritte auszuführen. Nach der Erstellung der Datei und den generellen Schritten soll also die ToolBox dem Kundenmodul mitteilen, dass eine neue Datei erstellt und von der ToolBox vorbereitet worden ist.


=== Ereignis-Server ===
=== Ereignis-Server ===


Der Ereignis-Server ist das Projekt, welches Ereignisse auslösen können soll, in unserem Szenario die ToolBox.
Der Ereignis-Server ist das Projekt, welches Ereignisse auslösen können soll, in unserem Szenario die ToolBox.  


==== Eigene Ereignisklasse ====
==== Eigene Ereignisklasse ====


* Erstellen Sie ein Klassenmodul, zum Beispiel 'clsEventServer'.
* Erstellen Sie ein Klassenmodul, zum Beispiel 'clsEventServer'.  
* Stellen Sie die Eigenschaft 'Instancing' auf den Wert '2 - PublicNotCreatable'.
* Stellen Sie die Eigenschaft 'Instancing' auf den Wert '2 - PublicNotCreatable'.
* Erstellen Sie die gewünschten Ereignisse: Public Event AfterCreateFile() Public Event BeforeLoadData(ByVal strDataFile As String, ByRef blnCancel As Boolean)
* Erstellen Sie die gewünschten Ereignisse:
 
Public Event AfterCreateFile()
Public Event BeforeLoadData(ByVal strDataFile As String, ByRef blnCancel As Boolean)
 
* wobei
* wobei
** 'AfterCreateFile' aufgerufen werden soll, nachdem die generellen Vorbereitungen einer neuen Datei abgeschlossen worden sind.
** 'AfterCreateFile' aufgerufen werden soll, nachdem die generellen Vorbereitungen einer neuen Datei abgeschlossen worden sind.
** 'BeforeLoadData' aufgerufen werden soll, bevor neue Daten in die offene Datei eingelesen werden.
** 'BeforeLoadData' aufgerufen werden soll, bevor neue Daten in die offene Datei eingelesen werden.  
*** Der Name der Datendatei soll beim Ereignis mit übergeben werden.
*** Der Name der Datendatei soll beim Ereignis mit übergeben werden.
*** Das Laden der Daten soll bei Bedarf abgebrochen werden können, indem der Parameter 'blnCancel' auf 'False' gesetzt wird.
*** Das Laden der Daten soll bei Bedarf abgebrochen werden können, indem der Parameter 'blnCancel' auf 'False' gesetzt wird.
* Erstellen Sie die entsprechenden Ereignis-Aufrufe: Public Sub RaiseEventAfterCreateFile() RaiseEvent AfterCreateFile End Sub Public Sub RaiseEventBeforeLoadData(ByVal strDataFile As String, ByRef blnCancel As Boolean) RaiseEvent BeforeLoadData(strDataFile, blnCancel) End Sub
* Erstellen Sie die entsprechenden Ereignis-Aufrufe:
 
Public Sub RaiseEventAfterCreateFile()
   
    RaiseEvent AfterCreateFile
End Sub
 
Public Sub RaiseEventBeforeLoadData(ByVal strDataFile As String, ByRef blnCancel As Boolean)
   
    RaiseEvent BeforeLoadData(strDataFile, blnCancel)
End Sub


==== Bereitstellung des Ereignis-Servers ====
==== Bereitstellung des Ereignis-Servers ====


Um den Ereignisse der Ereignisklasse auslösen zu können, muss ein permanenter Zugriff auf eine Modulvariable über eine Funktion bereitgestellt werden. Die Modulvariable sorgt dafür, dass immer auf die gleiche Instanz der Ereignisklasse zugegriffen wird, die Funktion stellt sicher, dass diese Instanz bereitgestellt wird:
Um den Ereignisse der Ereignisklasse auslösen zu können, muss ein permanenter Zugriff auf eine Modulvariable über eine Funktion bereitgestellt werden. Die Modulvariable sorgt dafür, dass immer auf die gleiche Instanz der Ereignisklasse zugegriffen wird, die Funktion stellt sicher, dass diese Instanz bereitgestellt wird:
* Erstellen Sie ein Modul, zum Beispiel 'modEventsToolBox'.
* Erstellen Sie ein Modul, zum Beispiel 'modEventsToolBox'.
* Fügen Sie wie hier gezeigt eine private Modulvariable und eine öffentliche Funktion hinzu: Private myEventServer As clsEventServer Public Function EventServer() As clsEventServer If myEventServer Is Nothing Then Set myEventServer = New clsEventServer Set EventServer = myEventServer End Function
* Fügen Sie wie hier gezeigt eine private Modulvariable und eine öffentliche Funktion hinzu:
 
Private myEventServer As clsEventServer
Public Function EventServer() As clsEventServer
    If myEventServer Is Nothing Then Set myEventServer = New clsEventServer
    Set EventServer = myEventServer
End Function


==== Auslösen eines Ereignisses ====
==== Auslösen eines Ereignisses ====


Innerhalb des Projektes, das die Ereignisse zur Verfügung stellt, können nun die Ereignisse wie folgt ausgelöst werden:
Innerhalb des Projektes, das die Ereignisse zur Verfügung stellt, können nun die Ereignisse wie folgt ausgelöst werden:
* Einfacher Aufruf eines Ereignisses ohne Parameter: EventServer.RaiseEventAfterCreateFile
 
* Aufruf eines Ereignisses mit Berücksichtigung des Abbruchs: Dim strDataFile As String Dim blnCancel As Boolean blnCancel = False '''EventServer.RaiseEventBeforeLoadData strDataFile, blnCancel''' If blnCancel = True Then ' Weitere Schritte abbrechen End If
* Einfacher Aufruf eines Ereignisses ohne Parameter:
    EventServer.RaiseEventAfterCreateFile        
 
* Aufruf eines Ereignisses mit Berücksichtigung des Abbruchs:
    Dim strDataFile As String
    Dim blnCancel As Boolean
   
    blnCancel = False
    '''EventServer.RaiseEventBeforeLoadData strDataFile, blnCancel'''
    If blnCancel = True Then
        ' Weitere Schritte abbrechen
    End If


=== Ereignis-Client ===
=== Ereignis-Client ===
Zeile 150: Zeile 214:


Analog zu Anwendungs-Ereignissen benötigt der Ereignis-Client eine Ereignis-Klasse:
Analog zu Anwendungs-Ereignissen benötigt der Ereignis-Client eine Ereignis-Klasse:
* Fügen Sie dem Kundenprojekt eine neue Klasse hinzu, zum Beispiel 'clsEventClient'.
* Fügen Sie dem Kundenprojekt eine neue Klasse hinzu, zum Beispiel 'clsEventClient'.
* Der Zugriff auf den Ereignis-Server erfolgt über eine private Klassenvariable: Private WithEvents myEvents As ToolBox.clsEventServer ' 'ToolBox' is der Name des Projektes des Ereignis-Servers
* Der Zugriff auf den Ereignis-Server erfolgt über eine private Klassenvariable:
 
Private WithEvents myEvents As ToolBox.clsEventServer     ' 'ToolBox' is der Name des Projektes des Ereignis-Servers
 
* '''Bitte beachten:''' Die Ereignisklasse 'clsEventServer' wird nur dann bereitgestellt, wenn deren Eigenschaft 'Instancing' den Wert '2 - PublicNotCreatable' hat!
* '''Bitte beachten:''' Die Ereignisklasse 'clsEventServer' wird nur dann bereitgestellt, wenn deren Eigenschaft 'Instancing' den Wert '2 - PublicNotCreatable' hat!
* das Ereignis 'Class_Initialize' der Ereignis-Klasse setzt die Klassenvariable auf die Instanz, welche der Ereignis-Server mit seiner Funktion 'EventServer' bereitstellt: Private Sub Class_Initialize() Set myEvents = ToolBox.EventServer End Sub
* Das Ereignis 'Class_Initialize' der Ereignis-Klasse setzt die Klassenvariable auf die Instanz, welche der Ereignis-Server mit seiner Funktion 'EventServer' bereitstellt:
* Die Ereignisse selbst können nun über die Auswahlfelder 'Objekt' und 'Prozedur' abgerufen werden: Private Sub myEvents_AfterCreateFile() End Sub Private Sub myEvents_BeforeLoadData(ByVal strDataFile As String, blnCancel As Boolean) End Sub
 
Private Sub Class_Initialize()
   
    Set myEvents = ToolBox.EventServer
End Sub
 
* Die Ereignisse selbst können nun über die Auswahlfelder 'Objekt' und 'Prozedur' abgerufen werden:
 
Private Sub myEvents_AfterCreateFile()
End Sub
 
Private Sub myEvents_BeforeLoadData(ByVal strDataFile As String, blnCancel As Boolean)
End Sub


==== Instanziierung der Ereignis-Klasse ====
==== Instanziierung der Ereignis-Klasse ====


Ebenfalls analog zu den Anwendungs-Ereignissen wird anschließend in einem Modul eine permanente Instanz der Ereignisklasse erstellt: Private myEvents As clsEventClient Public Sub Auto_Open() ' bzw. AutoOpen / AutoExec Set myEvents = New clsEventClient End Sub
Ebenfalls analog zu den Anwendungs-Ereignissen wird anschließend in einem Modul eine permanente Instanz der Ereignisklasse erstellt:
 
Private myEvents As clsEventClient
 
Public Sub Auto_Open()         ' bzw. AutoOpen / AutoExec
   
    Set myEvents = New clsEventClient
End Sub


== Andere Ereignisse zulassen mit 'DoEvents' ==
== Andere Ereignisse zulassen mit 'DoEvents' ==


Das Ausführen von Makros ist aus Sicht der Office-Anwendung (Word, Excel, PowerPoint etc.) ein exklusiver Vorgang: Andere Vorgänge können in dieser Zeit weder in der Anwendung noch in VBA ausgeführt werden. Das bedeutet, dass längere Vorgänge über längere Zeit die Anwendung komplett für sich beanspruchen und keine anderen Schritte zulassen können. Wenn Sie ganz bewusst diese Exklusivität unterbrechen möchten, um zum Beispiel auf eine Eingabe der Tastatur zu reagieren, verwenden Sie den Befehl 'DoEvents'. Dieser sorgt dafür, dass alle anstehenden Ereignisse der Office-Anwendung bzw. von VBA ausgeführt werden, bevor der unterbrochene Programmlauf wieder fortgesetzt wird. ;Konkretes Szenario Sie haben eine Schleife geschrieben, mit der tausende von Daten in einer Excel-Tabelle ausgewertet werden. Sie möchten gerne dafür sorgen, dass der Anwender diesen Vorgang mit der 'ESC'-Taste abbrechen kann. Da die Schleife keinen Raum für weitere Ereignisse bietet, wird das Drücken der 'ESC'-Taste erst dann von Excel entgegengenommen, wenn der aktuelle Programmlauf komplett abgeschlossen wurde. Abhilfe schafft hier ein Aufruf des 'DoEvents'-Befehls. Wenn der Programmlauf diesen Befehl antrifft, werden alle anstehenden Ereignisse abgearbeitet, bevor er weiter fortgesetzt wird, somit auch das Drücken der 'ESC'-Taste. '''Bitte beachten:''' Dieses Beispiel setzt voraus, dass zum Beispiel ein (ungebundener) Dialog auf das Drücken der 'ESC'-Taste reagieren kann, um dann wiederum die weitere Ausführung der Schleife abzubrechen. '''Wichtig:''' 'DoEvents' hat keiner Einfluss auf andere Programme oder das Verhalten Ihres Betriebssystems. VBA, Makros und somit 'DoEvents' betreffen ausschließlich die Office-Anwendung, in der sie ausgeführt werden.
Das Ausführen von Makros ist aus Sicht der Office-Anwendung (Word, Excel, PowerPoint etc.) ein exklusiver Vorgang: Andere Vorgänge können in dieser Zeit weder in der Anwendung noch in VBA ausgeführt werden. Das bedeutet, dass längere Vorgänge über längere Zeit die Anwendung komplett für sich beanspruchen und keine anderen Schritte zulassen können.
 
Wenn Sie ganz bewusst diese Exklusivität unterbrechen möchten, um zum Beispiel auf eine Eingabe der Tastatur zu reagieren, verwenden Sie den Befehl 'DoEvents'. Dieser sorgt dafür, dass alle anstehenden Ereignisse der Office-Anwendung bzw. von VBA ausgeführt werden, bevor der unterbrochene Programmlauf wieder fortgesetzt wird.
 
;Konkretes Szenario
Sie haben eine Schleife geschrieben, mit der tausende von Daten in einer Excel-Tabelle ausgewertet werden. Sie möchten gerne dafür sorgen, dass der Anwender diesen Vorgang mit der 'ESC'-Taste abbrechen kann. Da die Schleife keinen Raum für weitere Ereignisse bietet, wird das Drücken der 'ESC'-Taste erst dann von Excel entgegengenommen, wenn der aktuelle Programmlauf komplett abgeschlossen wurde.
 
Abhilfe schafft hier ein Aufruf des 'DoEvents'-Befehls. Wenn der Programmlauf diesen Befehl antrifft, werden alle anstehenden Ereignisse abgearbeitet, bevor er weiter fortgesetzt wird, somit auch das Drücken der 'ESC'-Taste.  
 
'''Bitte beachten:''' Dieses Beispiel setzt voraus, dass zum Beispiel ein (ungebundener) Dialog auf das Drücken der 'ESC'-Taste reagieren kann, um dann wiederum die weitere Ausführung der Schleife abzubrechen.
 
'''Wichtig:''' 'DoEvents' hat keiner Einfluss auf andere Programme oder das Verhalten Ihres Betriebssystems. VBA, Makros und somit 'DoEvents' betreffen ausschließlich die Office-Anwendung, in der sie ausgeführt werden.

Version vom 10. Oktober 2018, 16:04 Uhr

Auto-Makros

Auto-Makros werden beim Starten bzw. beim Beenden der Anwendung und / oder beim Öffnen bzw. beim Schließen der Datei, welche das Auto-Makro enthält, ausgeführt. Sie stehen in den drei Anwendungen Word, Excel und PowerPoint zur Verfügung, unterscheiden sich jedoch teilweise in Schreibweise und Einsatzgebiet.

Word

Name Beschreibung Anwendungsbereich
AutoNew Wird ausgeführt, wenn
  • von dieser Vorlage ein neues Dokument erzeugt wird
Vorlagen
AutoOpen Wird ausgeführt, wenn
  • dieses Dokument
  • diese Vorlage geöffnet wird
Vorlagen
Dokumente
AutoClose Wird ausgeführt, wenn
  • dieses Dokument
  • diese Vorlage geschlossen wird
Vorlagen
Dokumente
AutoExec Wird ausgeführt, wenn
  • Word gestartet bzw.
  • das Add-In geladen wird
Ausschließlich Add-Ins und Normal.dot(m)
AutoExit Wird ausgeführt, wenn
  • Word beendet bzw.
  • das Add-In entladen wird
Ausschließlich Add-Ins und Normal.dot(m)

Excel

Name Beschreibung Anwendungsbereich
Auto_Open Wird ausgeführt, wenn
  • diese Arbeitsmappe / diese Vorlage geöffnet wird
  • dieses Add-In geladen bzw. Excel gestartet wird
Vorlagen
Arbeitsmappen
Add-Ins
Auto_Close Wird ausgeführt, wenn
  • diese Arbeitsmappe / diese Vorlage geschlossen wird
  • dieses Add-In entladen bzw. Excel beendet wird
Vorlagen
Arbeitsmappen
Add-Ins

PowerPoint

In PowerPoint stehen die Auto-Makros ausschließlich in Add-Ins zur Verfügung. Wenn Sie auch in einer Präsentation einen Weg benötigen, um beim Starten / Laden etwas auszuführen (um zum Beispiel auf Ereignisse zuzugreifen), können Sie (ab PowerPoint 2007) alternativ ein (leeres) Ribbon erzeugen und dessen 'onLoad'-Callback einsetzen.

Name Beschreibung Anwendungsbereich
Auto_Open Wird ausgeführt, wenn
  • dieses Add-In geladen bzw. PowerPoint gestartet wird
Ausschließlich in Add-Ins
Auto_Close Wird ausgeführt, wenn
  • dieses Add-In entladen bzw. PowerPoint beendet wird
Ausschließlich in Add-Ins


Benutzeroberflächen-Ereignisse

Dialog-Ereignisse

Ereignisse des Menübandes

Dokument- (Präsentations- bzw. Arbeitsmappen-) Ereignisse

Anwendungsereignisse

Die Anwendungsereignisse werden von der entsprechenden Office-Anwendung zur Verfügung gestellt und können wie hier beschrieben mithilfe einer Ereignisklasse abgerufen werden.

Sie umfassen typischerweise Ereignisse wie das Öffnen, Drucken, Speichern von Dateien und reagieren auf Benutzerinteraktion wie das Ändern der Auswahl, das Wechseln zu einer anderen offenen Datei etc.

Ereignisklasse

1. Deklarieren Sie eine Objektvariable, welche die Anwendung entgegennehmen soll, deren Ereignisse Sie empfangen möchten. Beachten Sie dabei das Schlüsselwort WithEvents:

Private WithEvents myEvents As Application

2. Initialisieren Sie diese Variable bei der Initialisierung der Klasse.

Private Sub Class_Initialize()
   
   Set myEvents = Application
End Sub

3. Nun stehen Ihnen die Anwendungs-Ereignisse zur Verfügung:

  • Setzen Sie die Auswahl 'Objekt' auf 'myEvents'
  • Wählen Sie in der Liste 'Prozedur' das gewünschte Ereignis

Bitte beachten: Verwenden Sie immer die Prozedur-Liste, um ein neues Ereignis hinzuzufügen, weil viele Ereignisse Übergabeparameter verwenden.

Ereignisprozedur in einem eigenen Modul

1. Erstellen Sie ein Modul, welches die Ereignisklasse ansprechen soll.

2. Deklarieren Sie eine Objektvariable, welche die Ereignisklasse entgegennimmt. Da der Zugriff auf die Ereignisse permanent sein soll, verwenden Sie eine Modulvariable:

Private myEvents As clsEvents

3. Erstellen Sie eine Prozedur, welche die Ereignisklasse instanziiert. Hierfür eignet sich das passende Auto-Makro, welches beim Starten bzw. Öffnen ausgeführt wird.

Public Sub Auto_Open()
   
   Set myEvents = New clsEventsExcel
End Sub

Wichtige Hinweise

  • Die Ereignisse können erst von Ihnen abgefangen werden, wenn die Klasse instanziiert wurde. Führen Sie dazu das Automakro aus, das Sie zu diesem Zweck erstellt haben.
  • Die Verbindung zu den Ereignissen kann in der Entwicklungsphase verloren gehen, wenn beim Testen Fehler auftreten oder wenn Sie größere Teile der Programmierung bearbeiten. Sie können bei Bedarf durch das Ausführen des Automakros diese wieder aktivieren.

Eigene Ereignisse

Wenn Sie eine auf mehrere Projekte verteilte Lösung entwickeln, können Sie eigene Ereignisse auslösen und entsprechend darauf reagieren. Sie können eigene Ereignisse zwar auch innerhalb eines einzelnen Projektes verwenden, hier würde der Nutzen jedoch nicht den Aufwand rechtfertigen, weil nach der Abarbeitung eines Schrittes der nächste Schritt direkt aufgerufen werden kann.

Szenario

Sie verwenden in Ihren Lösungen eine gemeinsame ToolBox, welche all jene Hilfefunktionen enthält, die für alle Lösungen relevant sind. Für die Kundenanpassungen verwenden Sie ein eigenes Add-In, welches die kundenspezifische Funktionalitäten enthält. Das Kundenmodul hat eine Referenz auf die ToolBox, damit Sie auf dessen Hilfsfunktionen zugreifen können.

Eine Aufgabe Ihrer Lösung besteht darin, eine neue Datei zu erstellen. Die Aufgabe wird größtenteils von der ToolBox erfüllt, aber im Anschluss möchten Sie die Möglichkeit haben, zusätzliche kundenspezifische Schritte auszuführen. Nach der Erstellung der Datei und den generellen Schritten soll also die ToolBox dem Kundenmodul mitteilen, dass eine neue Datei erstellt und von der ToolBox vorbereitet worden ist.

Ereignis-Server

Der Ereignis-Server ist das Projekt, welches Ereignisse auslösen können soll, in unserem Szenario die ToolBox.

Eigene Ereignisklasse

  • Erstellen Sie ein Klassenmodul, zum Beispiel 'clsEventServer'.
  • Stellen Sie die Eigenschaft 'Instancing' auf den Wert '2 - PublicNotCreatable'.
  • Erstellen Sie die gewünschten Ereignisse:
Public Event AfterCreateFile()
Public Event BeforeLoadData(ByVal strDataFile As String, ByRef blnCancel As Boolean)
  • wobei
    • 'AfterCreateFile' aufgerufen werden soll, nachdem die generellen Vorbereitungen einer neuen Datei abgeschlossen worden sind.
    • 'BeforeLoadData' aufgerufen werden soll, bevor neue Daten in die offene Datei eingelesen werden.
      • Der Name der Datendatei soll beim Ereignis mit übergeben werden.
      • Das Laden der Daten soll bei Bedarf abgebrochen werden können, indem der Parameter 'blnCancel' auf 'False' gesetzt wird.
  • Erstellen Sie die entsprechenden Ereignis-Aufrufe:
Public Sub RaiseEventAfterCreateFile()
    
    RaiseEvent AfterCreateFile
End Sub
Public Sub RaiseEventBeforeLoadData(ByVal strDataFile As String, ByRef blnCancel As Boolean)
    
    RaiseEvent BeforeLoadData(strDataFile, blnCancel)
End Sub

Bereitstellung des Ereignis-Servers

Um den Ereignisse der Ereignisklasse auslösen zu können, muss ein permanenter Zugriff auf eine Modulvariable über eine Funktion bereitgestellt werden. Die Modulvariable sorgt dafür, dass immer auf die gleiche Instanz der Ereignisklasse zugegriffen wird, die Funktion stellt sicher, dass diese Instanz bereitgestellt wird:

  • Erstellen Sie ein Modul, zum Beispiel 'modEventsToolBox'.
  • Fügen Sie wie hier gezeigt eine private Modulvariable und eine öffentliche Funktion hinzu:
Private myEventServer As clsEventServer


Public Function EventServer() As clsEventServer

    If myEventServer Is Nothing Then Set myEventServer = New clsEventServer
    Set EventServer = myEventServer
End Function

Auslösen eines Ereignisses

Innerhalb des Projektes, das die Ereignisse zur Verfügung stellt, können nun die Ereignisse wie folgt ausgelöst werden:

  • Einfacher Aufruf eines Ereignisses ohne Parameter:
   EventServer.RaiseEventAfterCreateFile          
  • Aufruf eines Ereignisses mit Berücksichtigung des Abbruchs:
   Dim strDataFile As String
   Dim blnCancel As Boolean
   
   blnCancel = False
   EventServer.RaiseEventBeforeLoadData strDataFile, blnCancel
   If blnCancel = True Then
       ' Weitere Schritte abbrechen
   End If

Ereignis-Client

Der Ereignis-Client ist das Projekt, welches auf Ereignisse reagieren können soll, in unserem Szenario das Kundenmodul. Das Projekt benötigt eine Referenz auf das Projekt des Ereignis-Servers (in unserem Szenario die ToolBox).

Ereignis-Klasse

Analog zu Anwendungs-Ereignissen benötigt der Ereignis-Client eine Ereignis-Klasse:

  • Fügen Sie dem Kundenprojekt eine neue Klasse hinzu, zum Beispiel 'clsEventClient'.
  • Der Zugriff auf den Ereignis-Server erfolgt über eine private Klassenvariable:
Private WithEvents myEvents As ToolBox.clsEventServer     ' 'ToolBox' is der Name des Projektes des Ereignis-Servers
  • Bitte beachten: Die Ereignisklasse 'clsEventServer' wird nur dann bereitgestellt, wenn deren Eigenschaft 'Instancing' den Wert '2 - PublicNotCreatable' hat!
  • Das Ereignis 'Class_Initialize' der Ereignis-Klasse setzt die Klassenvariable auf die Instanz, welche der Ereignis-Server mit seiner Funktion 'EventServer' bereitstellt:
Private Sub Class_Initialize()
    
    Set myEvents = ToolBox.EventServer
End Sub
  • Die Ereignisse selbst können nun über die Auswahlfelder 'Objekt' und 'Prozedur' abgerufen werden:
Private Sub myEvents_AfterCreateFile()

End Sub
Private Sub myEvents_BeforeLoadData(ByVal strDataFile As String, blnCancel As Boolean)

End Sub

Instanziierung der Ereignis-Klasse

Ebenfalls analog zu den Anwendungs-Ereignissen wird anschließend in einem Modul eine permanente Instanz der Ereignisklasse erstellt:

Private myEvents As clsEventClient
Public Sub Auto_Open()          ' bzw. AutoOpen / AutoExec
    
    Set myEvents = New clsEventClient
End Sub

Andere Ereignisse zulassen mit 'DoEvents'

Das Ausführen von Makros ist aus Sicht der Office-Anwendung (Word, Excel, PowerPoint etc.) ein exklusiver Vorgang: Andere Vorgänge können in dieser Zeit weder in der Anwendung noch in VBA ausgeführt werden. Das bedeutet, dass längere Vorgänge über längere Zeit die Anwendung komplett für sich beanspruchen und keine anderen Schritte zulassen können.

Wenn Sie ganz bewusst diese Exklusivität unterbrechen möchten, um zum Beispiel auf eine Eingabe der Tastatur zu reagieren, verwenden Sie den Befehl 'DoEvents'. Dieser sorgt dafür, dass alle anstehenden Ereignisse der Office-Anwendung bzw. von VBA ausgeführt werden, bevor der unterbrochene Programmlauf wieder fortgesetzt wird.

Konkretes Szenario

Sie haben eine Schleife geschrieben, mit der tausende von Daten in einer Excel-Tabelle ausgewertet werden. Sie möchten gerne dafür sorgen, dass der Anwender diesen Vorgang mit der 'ESC'-Taste abbrechen kann. Da die Schleife keinen Raum für weitere Ereignisse bietet, wird das Drücken der 'ESC'-Taste erst dann von Excel entgegengenommen, wenn der aktuelle Programmlauf komplett abgeschlossen wurde.

Abhilfe schafft hier ein Aufruf des 'DoEvents'-Befehls. Wenn der Programmlauf diesen Befehl antrifft, werden alle anstehenden Ereignisse abgearbeitet, bevor er weiter fortgesetzt wird, somit auch das Drücken der 'ESC'-Taste.

Bitte beachten: Dieses Beispiel setzt voraus, dass zum Beispiel ein (ungebundener) Dialog auf das Drücken der 'ESC'-Taste reagieren kann, um dann wiederum die weitere Ausführung der Schleife abzubrechen.

Wichtig: 'DoEvents' hat keiner Einfluss auf andere Programme oder das Verhalten Ihres Betriebssystems. VBA, Makros und somit 'DoEvents' betreffen ausschließlich die Office-Anwendung, in der sie ausgeführt werden.