Ereignisse: Unterschied zwischen den Versionen
Pwania (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
Pwania (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
[[Category:vba-wiki]] | |||
== Anwender und Anwendung == | |||
Eigentlich ist es wie im echten Leben: Wir werden bestimmt von Geschehnissen und Entscheidungen. | |||
Bei der Programmierung ist es nicht anders, nur dass hier zwischen Anwender-Ereignissen und Anwendungs-Ereignissen unterschieden wird. | |||
Die Anwender-Ereignisse sind bei dieser Analogie als Entscheidungen zu sehen, das bedeutet, der Anwender hat einen Text eingegeben, einen Knopf gedrückt oder eine Frage bestätigt, wodurch in der Programmierung nun weitere Schritte durchgeführt werden. | |||
Die Anwendungs-Ereignisse sind hingegen analog zu Geschehnissen zu betrachten, welche aus Sicht der Programmierung willkürlich (eine neue Datei wird angelegt) oder geplant (nach Ablauf einer vorgegebenen Zeit) eintreten können. | |||
Ereignisse bestimmen also die Arbeitsabläufe letztendlich sämtlicher Programme. Unser Rechner ist nichts weiter als eine übertrieben komplizierte elektrische Wärmequelle, wenn nicht zu bestimmten Ereignissen oder als Reaktion auf eine Benutzereingabe immer mal wieder eine Aufgabe erfüllt werden könnte ... | |||
== Auto-Makros == | == Auto-Makros == | ||
Zeile 71: | Zeile 84: | ||
| Auto_Open | | Auto_Open | ||
| Wird ausgeführt, wenn | | Wird ausgeführt, wenn | ||
* dieses Add-In geladen | * dieses Add-In geladen wird (beim Starten von PowerPoint) | ||
| 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 | * dieses Add-In entladen wird (wenn PowerPoint beendet wird) | ||
| Ausschließlich in Add-Ins | | Ausschließlich in Add-Ins | ||
|} | |} | ||
== Benutzeroberflächen-Ereignisse == | == Benutzeroberflächen-Ereignisse == | ||
=== Dialog-Ereignisse === | === Dialog-Ereignisse === | ||
Siehe [[UserForms|Eigene Dialoge (Userforms)]] | |||
=== Ereignisse des Menübandes === | === Ereignisse des Menübandes === | ||
Siehe [[Menüband|Menüband (Ribbon)]] | |||
== Dokument- (Präsentations- bzw. Arbeitsmappen-) Ereignisse == | == Dokument- (Präsentations- bzw. Arbeitsmappen-) Ereignisse == |
Aktuelle Version vom 28. Januar 2023, 00:34 Uhr
Anwender und Anwendung
Eigentlich ist es wie im echten Leben: Wir werden bestimmt von Geschehnissen und Entscheidungen.
Bei der Programmierung ist es nicht anders, nur dass hier zwischen Anwender-Ereignissen und Anwendungs-Ereignissen unterschieden wird.
Die Anwender-Ereignisse sind bei dieser Analogie als Entscheidungen zu sehen, das bedeutet, der Anwender hat einen Text eingegeben, einen Knopf gedrückt oder eine Frage bestätigt, wodurch in der Programmierung nun weitere Schritte durchgeführt werden.
Die Anwendungs-Ereignisse sind hingegen analog zu Geschehnissen zu betrachten, welche aus Sicht der Programmierung willkürlich (eine neue Datei wird angelegt) oder geplant (nach Ablauf einer vorgegebenen Zeit) eintreten können.
Ereignisse bestimmen also die Arbeitsabläufe letztendlich sämtlicher Programme. Unser Rechner ist nichts weiter als eine übertrieben komplizierte elektrische Wärmequelle, wenn nicht zu bestimmten Ereignissen oder als Reaktion auf eine Benutzereingabe immer mal wieder eine Aufgabe erfüllt werden könnte ...
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
|
Vorlagen |
AutoOpen | Wird ausgeführt, wenn
|
Vorlagen Dokumente |
AutoClose | Wird ausgeführt, wenn
|
Vorlagen Dokumente |
AutoExec | Wird ausgeführt, wenn
|
Ausschließlich Add-Ins und Normal.dot(m) |
AutoExit | Wird ausgeführt, wenn
|
Ausschließlich Add-Ins und Normal.dot(m) |
Excel
Name | Beschreibung | Anwendungsbereich |
---|---|---|
Auto_Open | Wird ausgeführt, wenn
|
Vorlagen Arbeitsmappen Add-Ins |
Auto_Close | Wird ausgeführt, wenn
|
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
|
Ausschließlich in Add-Ins |
Auto_Close | Wird ausgeführt, wenn
|
Ausschließlich in Add-Ins |
Benutzeroberflächen-Ereignisse
Dialog-Ereignisse
Siehe Eigene Dialoge (Userforms)
Ereignisse des Menübandes
Siehe Menüband (Ribbon)
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.