Ereignisprozeduren implantieren

Ereignisse kann man nicht nur innerhalb des jeweiligen Klassenmoduls eines Objekts wie in Formularen oder Berichten abfangen. Sie können auch Code in Klassenmodulen, Formular- und Berichtsmodulen unterbringen, der die Ereignisse anderer Klassenmodule abfängt und sich dort einklinkt. Dieser Beitrag zeigt, wie nützlich dies sein kann und wie es überhaupt funktioniert.

Im Beitrag Ereignisprozeduren (Shortlink 684) haben wir einige Grundlagen zur Programmierung der Ereignisprozeduren von Formularen und Berichten sowie darin enthaltener Steuerelementen beschrieben. Was wir dort nur angerissen haben, ist die Tatsache, dass Sie sich auch von außerhalb des betroffenen Objekts und zur Laufzeit in die Ereigniskette einschleichen können.

Was um Himmels willen soll man denn damit anfangen Bevor wir Beispiele liefern, zunächst einmal die grundsätzliche Vorgehensweise. Normalerweise schreiben Sie Ereignisprozeduren in das Klassenmodul des jeweiligen Formulars oder Berichts und stellen die Ereigniseigenschaften auf den Wert [Ereignisprozedur] oder [Event Procedure] ein, damit das Formular oder der Bericht weiß, dass für ein Ereignis eine entsprechende Prozedur vorhanden ist.

Solche Ereignisse kann man aber auch außerhalb des eigentlichen Klassenmoduls nutzen, indem man eine Objektvariable mit einer Referenz auf das Formular oder den Bericht deklariert und instanziert – und das unter Zuhilfenahme eines speziellen Schlüsselworts namens WithEvents.

Der Beispielaufbau besteht aus zwei ungebundenen Formularen namens frmEreignisAbfangen und frmFormularMitEreignis. Ersteres enthält lediglich eine Schaltfläche namens cmdSetReference und sieht wie in Abb. 1 aus.

pic001.png

Abb. 1: Dieses Formular wird gleich die Ereignisse eines anderen Formulars abfangen.

Das Formular frmFormularMitEreignis ist ein komplett leeres Formular, das lediglich Ereignisprozeduren für die Ereignisse Beim Öffnen und Beim Schließen enthält:

Private Sub Form_Close()
    MsgBox "Formular wird geschlossen."
    End Sub
Private Sub Form_Open(Cancel As Integer)
    MsgBox "Formular wird geöffnet."
    End Sub

Der Schaltfläche cmdSetReference weisen Sie nun die folgende Ereignisprozedur zu – nicht ohne eine Objektvariable namens objForm mit dem Schlüsselwort WithEvents im Kopf des Klassenmoduls des Formulars zu referenzieren:

Dim WithEvents objForm As Form
Private Sub cmdSetReference_Click()
    DoCmd.OpenForm "frmFormularMitEreignis"
    Set objForm = Forms!frmFormularMitEreignis
    End Sub

Bei einem Mausklick auf die Schaltfläche geschieht nichts Unerwartetes: Die Routine öffnet das Formular frmFormularMitEreignis, welches wiederum mit der oben definierten Meldung anzeigt, dass es geöffnet wurde. Gleiches geschieht, wenn Sie es wieder schließen.

Ereignis einschleusen

Dank der Deklaration von objForm mit dem Schlüsselwort WithEvents können wir im Klassenmodul des Formulars frmEreignisAbfangen Ereignisprozeduren für das mit objForm referenzierte Formular festlegen.

Das geht am einfachsten, indem Sie aus dem linken Kombinationsfeld des Codefensters mit dem Modul Form_frmEreignisAbfangen den Eintrag objForm und aus dem rechten Fenster zum Beispiel den Eintrag Open auswählen. Probieren wir dies am Beispiel des Close-Ereignisses des Objekts objForm aus:

Private Sub objForm_Close()
    MsgBox "Implantiert: Formular wurde
    geschlossen."
    End Sub

Wenn Sie die Schaltfläche nun betätigen und das Formular frmFormularMitEreignis anschließend wieder schließen, erscheinen zwei Meldungsfenster – das erste mit dem Text Implantiert: Formular wurde geschlossen und schließlich die Meldung aus dem Formular frmFormularMitEreignis selbst.

Das Fazit lautet: Sie können Ereignisse für ein Formular auch von außen festlegen, wenn Sie nur eine Objektvariable mit WithEvents deklarieren und damit auf das Zielformular verweisen. Hierbei gibt es noch einige weitere Möglichkeiten und auch Punkte, die Sie beachten müssen – fürs Erste soll dies jedoch ausreichen, sodass wir uns nun wichtigeren Dingen zuwenden: Wofür brauchen wir das Ganze überhaupt

Beispiele für die vorgestellte Technik

In den folgenden Abschnitten zeigen wir Ihnen an zwei Beispielen, wie Sie durch das Implantieren einer Ereignisprozedur von einem Formular in ein anderes Vorteile erzielen und den Entwurf Ihrer Anwendung verbessern können.

Beispiel Detailformular

Das erste Beispiel, bei dem das Implantieren einer Ereignisprozedur eine Verbesserung hervorruft, ist die typische Vorgehensweise beim Öffnen eines Detailformulars von einer Übersichtsliste aus zum Anlegen eines neuen Datensatzes (Objekte in der Beispieldatenbank: frmArtikeluebersicht_I, sfmArtikeluebersicht_I, frmArtikeldetails_I). Abb. 2 zeigt das Übersichtsformular mit einer Anzeigen-Schaltfläche, die den Detaildialog aus Abb. 3 öffnen soll. Normalerweise ist dafür etwa folgender Code verantwortlich, den Sie für die Ereigniseigenschaft Beim Klicken hinterlegen:

pic002.png

Abb. 2: Mit der Anzeigen-Schaltfläche dieses Formulars öffnen Sie …

pic003.png

Abb. 3: … dieses Detailformular.

Private Sub cmdNeu_Click()
    DoCmd.OpenForm "frmArtikeldetails_I", _
    DataMode:=acFormAdd, WindowMode:=acDialog
    Me!sfmArtikeluebersicht.Form.Requery
    End Sub

Diese Routine öffnet das Detailformular als modalen Dialog, das heißt, dass der aufrufende Code erst weiterläuft, wenn das Formular wieder geschlossen ist. Genau dann führt die Routine noch eine Anweisung aus, die den Inhalt des Unterformulars mit der Übersicht der Datensätze aktualisiert, damit dieses den über das Detailformular hinzugefügten Datensatz direkt anzeigt.

Nachteil Detailformular, Version I

Der Nachteil hierbei ist in manchen Fällen, dass der Benutzer nicht auf die Daten im aufrufenden Formular zugreifen kann, solange das Detailformular geöffnet ist (manchmal ist dies auch gewollt – in diesen Fällen reicht die obige Technik natürlich aus).

Verbesserung Detailformular

Wenn Sie auf das Übersichtsformular zugreifen möchten, während das Detailformular geöffnet ist, rufen Sie dieses mit folgender Anweisung auf – also wie oben, nur ohne den Parameter WindowMode auf acDialog einzustellen:

DoCmd.OpenForm "frmArtikeldetails_I",
DataMode:=acFormAdd

Das Detailformular verschwindet nun allerdings hinter dem Übersichtsformular, was Sie durch Einstellen der Eigenschaft Popup des Detailformulars auf den Wert Ja ändern. Sie können dann auf das Übersichtsformular zugreifen, während das Detailformular geöffnet ist (s. Abb. 4).

pic004.png

Abb. 4: Arbeiten im Übersichtsformular, während das Detailformular geöffnet ist

Wenn Sie allerdings wollen, dass der neue Datensatz gleich nach dem Schließen des Detailformulars im Übersichtsformular angezeigt wird, können Sie mit einem Requery in der aufrufenden Routine direkt hinter dem DoCmd.OpenForm nichts erreichen: Da das Detailformular nicht als modaler Dialog geöffnet wird, hält Access auch die Ausführung des Codes nicht an und ruft die Requery-Anweisung unmittelbar nach dem Öffnen des Detailformulars auf, was hier nicht hilfreich ist.

Wie aber bekommen wir nun mit, wann der Benutzer das Detailformular schließt und wir das Hauptformular aktualisieren müssen Hier setzen wir mit einem Ereignisprozedur-Implantat an. Deklarieren Sie im Kopf des Klassenmoduls des Formulars frmArtikelUebersicht_I eine Objektvariable, die eine Referenz auf das geöffnete Formular enthält:

Dim WithEvents objFrmArtikelDetails_I As Form

Diese Variable füllen Sie in der Ereignisprozedur, die das Detailformular öffnet:

Set objFrmArtikelDetails_I =
Forms!frmArtikeldetails_I

Nun brauchen Sie nur noch ein Ereignis für das Detailformular im Klassenmodul des Übersichtsformulars anzulegen, das beim Schließen des Detailformulars ausgelöst wird und das Unterformular mit der Datenübersicht aktualisiert:

Private Sub objFrmArtikelDetails_I_Close()
    Me!sfmArtikeluebersicht.Requery
    End Sub

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

Workplace

Jahresabonnement TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar