|  | Unser Angebot für Sie! Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'! |
| |
Zusammenfassung
Öffnen Sie modale Dialoge auf alternative Art und profitieren Sie vom daraus resultierenden vereinfachten Datenaustausch.
Techniken
Formulare, VBA, Ereignisprozeduren
Voraussetzungen
Access 2000 und höher
Beispieldateien
ModaleDialoge.mdb
Shortlink
682
Modale Dialoge mal anders
André Minhorst, Duisburg
Unter modalen Dialogen verstehen wir Formulare zur Eingabe von Daten, die so geöffnet werden, dass der Benutzer während der Eingabe nichts anderes in Access erledigen kann als in diesem Formular zu arbeiten. Zum Öffnen eines solchen Formulars verwendet man üblicherweise den Parameter WindowMode:=acDialog, was den praktischen Nebeneffekt hat, dass der aufrufende Code stehen bleibt. Wir zeigen, welche Vor- und Nachteile dies bringt und welche Alternative es gibt.
Der übliche Ablauf beim Einsatz modaler Dialoge, etwa zum Anlegen eines neuen Datensatzes, ist dieser:
Sie öffnen das Formular mit einer Anweisung wie folgt:
DoCmd.OpenForm "Formularname", WindowMode:=acDialog, DataMode:=acFormAdd, OpenArgs:=lngId
Dabei sorgt WindowMode:=acDialog für das Öffnen als modaler Dialog. DataMode:=acFormAdd teilt dem Formular mit, dass es nur einen neuen, leeren Datensatz anzeigen soll, und mit OpenArgs übergeben Sie optional eine Information wie etwa den Fremdschlüsselwert für die Verknüpfung des neuen Datensatzes mit der übergeordneten Tabelle.
Das Popup-Formular öffnet sich, der Benutzer kann nichts anderes tun, als die Daten einzugeben (alle anderen Access-Elemente sind in dieser Zeit tabu), und dann schließt der Benutzer das Formular auf eine von zwei Arten. Die erste offeriert in der Regel eine OK-Schaltfläche, die das Formular mit der folgenden Anweisung unsichtbar schaltet:
Me.Visible = False
Die zweite schließt das Formular gleich komplett:
DoCmd.Close acForm, Me.Name
Beide sorgen dafür, dass das Formular verschwindet und dass der aufrufende Code weiterläuft, da das Formular den Fokus abgegeben hat. Wo aber ist der Unterschied? Er liegt darin, dass der aufrufende Code noch auf das unsichtbare Formular zugreifen kann, um den Inhalt seiner Steuerelemente einzulesen - in den meisten Fällen holt es sich dabei die ID des neu angelegten Datensatzes. Dazu muss die Routine prüfen, ob das Formular noch geöffnet ist, was dann als sicheres Indiz dafür gilt, dass es über die OK-Schaltfläche »geschlossen« wurde:
If IstFormularGeoeffnet("Formularname") Then
‚Lese wichtige Felder aus
End If
Welche Nachteile hat dies? Im Wesentlichen die folgenden zwei:
Die Datenübergabe an das aufgerufene Formular ist je nach Anzahl der zu übergebenden Informationen aufwendig, weil prinzipiell nur der OpenArgs-Parameter dafür bereitsteht. Und dem kann man mehrere Parameter gleichzeitig auch nur dann unterjubeln, wenn man diese mit einem geeigneten Trennzeichen oder einem anderen speziellen Format auszeichnet und im aufgerufenen Formular entsprechend parst.
Gleichzeitig müssen Sie eine Abhängigkeit vom Popup-Formular zum aufrufenden Formular eingehen. Wenn der Benutzer das Popup-Formular mit der OK-Schaltfläche schließt, wird dieses ja nur unsichtbar geschaltet. Das aufrufende Formular muss es dann nach dem Auslesen der Daten noch schließen. Das ist nicht gut, denn: Wenn die aufrufende Instanz dies nicht weiß, bleibt das Popup-Formular geöffnet. Das wiederum führt dazu, dass beim nächsten Öffnen per DoCmd.OpenForm verwendete Parameter wirkungslos verpuffen.
Alles neu
Schauen wir uns also die alternative Variante an. Diese soll Folgendes ermöglichen:
- Übergabe beliebig vieler Parameter
- Problemloses Auslesen der Steuerelemente des Popup-Formulars vor dem Schließen
- Tatsächliches Schließen des Formulars nach Klick auf die OK-Schaltfläche
Wie funktioniert das? Der erste Schritt ist, dass wir das Formular nicht auf dem üblichen Wege als modalen Dialog öffnen. Alternativ instanzieren wir dieses als Objekt auf Basis des Klassenmoduls des Formulars. Falls Sie so etwas noch nie gemacht haben: Keine Angst, die folgenden Abschnitte vermitteln keine Raketentechnik. Voraussetzung hierfür ist, dass das Popup-Formular ein Klassenmodul besitzt. Das können wir aber voraussetzen, wenn dieses mindestens über Schaltflächen mit angehängtem VBA-Code zum Schließen des Formulars verfügt.
Beispielsweise ...
Für diesen Beitrag halten die Tabellen der Südsturm-Datenbank her (eine angepasste Variante der Nordwind-Datenbank), und hier im Speziellen tblKategorien und tblArtikel. Das Formular frmKategorienArtikel aus Abb. 1 verwaltet die Kategorien und die jeweils darin enthaltenen Daten. Eine Schaltfläche namens cmdNeuerArtikel soll das Popup-Formular frmNeuerArtikel öffnen (s. Abb. 2).
Abb. 1: Dieses Formular ruft ein Popup-Formular auf alternative Weise auf.
Abb. 2: Popup-Formular zum Anlegen neuer Artikel
Damit wir einen praktischen Anwendungsfall für das Übergeben von Parametern und das Auslesen von Steuerelementen haben, soll das Popup-Formular das Feld Kategorie mit einer Voreinstellung belegen. Diese entspricht der Kategorie, die im Formular frmKategorienArtikel zum Zeitpunkt des Klicks auf cmdNeuerArtikel eingestellt ist.
Außerdem soll das Formular frmKategorienArtikel vor dem Schließen des Popup-Formulars frmNeuerArtikel die ID des neuen Artikels einlesen und den Datensatzzeiger des Unterformulars sfmKategorienArtikel darauf einstellen.
Für den nächsten Schritt muss das Popup-Formular ein Klassenmodul enthalten. Dazu legen wir einfach schon einmal die folgenden beiden Ereignisprozeduren für die Schaltflächen cmdOK und cmdAbbrechen an. Beide schließen das Formular, die Schaltfläche cmdAbbrechen macht zuvor noch die Änderungen rückgängig:
Private Sub cmdOK_Click()
DoCmd.Close acForm, Me.Name
End Sub
Private Sub cmdAbbrechen_Click()
Me.Undo
DoCmd.Close acForm, Me.Name
End Sub
Beim Aufruf des Popup-Formulars sind nun ein paar Schritte mehr erforderlich als beim puren DoCmd.OpenForm. Der erste ist, dass Sie eine Objektvariable für das Klassenmodul des Popup-Formulars im Kopf des Moduls des aufrufenden Formulars anlegen:
Dim objFrmNeuerArtikel As Form_frmNeuerArtikel
Beim Klicken auf die Schaltfläche cmdNeuerArtikel wird dann diese Routine ausgelöst:
Private Sub cmdNeuerArtikel_Click()
Set objFrmNeuerArtikel =
New Form_frmNeuerArtikel
With objFrmNeuerArtikel
.DefaultEditing = 1
.Modal = True
.Visible = True
End With
End Sub
Die Routine erzeugt zunächst eine neue Instanz des Klassenmoduls Form_frmNeuerArtikel, was zusammen mit dem Sichtbarmachen einem herkömmlichen DoCmd.OpenForm-Aufruf entspricht. Hinzu kommt das Einstellen der verborgenen Eigenschaft DefaultEditing auf den Wert 1 und der Eigenschaft Modal auf True. Letzteres bewirkt zusammen mit dem Setzen der Eigenschaft Popup des Formulars die Anzeige des Formulars als modaler Dialog. Hier gibt es einen wichtigen Unterschied im Vergleich zu der Wirkung von DoCmd.OpenForm "frm", WindowMode:=acDialog: Der Benutzer kann zwar genauso wenig auf die übrigen Access-Elemente zugreifen, während das Formular geöffnet ist, aber der aufrufende Code läuft weiter. Und genau das eröffnet ganz neue Möglichkeiten - dazu jedoch später mehr.
|