Formatassistent für Textfelder, Teil 2

Im ersten Teil dieser Beitragsreihe haben wir einen Assistenten vorgestellt, mit dem Sie die Format-Eigenschaft von Feldern in Tabellen, Abfragen, Formularen und Berichten einstellen können. Diesem Assistenten fügen wir noch eine weitere nützliche Funktion hinzu. Dabei wollen wir die Daten, die in diesem Feld angezeigt werden, auslesen und im Formatassistenten anzeigen, damit der Benutzer das Ergebnis der Formatierung direkt anhand seiner eigenen Daten betrachten kann. Dazu ist, wenn wir auf die Daten der gerade angezeigten Tabelle zugreifen wollen, noch ein kleiner Trick nötig, denn wir können nicht auf die Daten zugreifen, solange die Tabelle in der Entwurfsansicht geöffnet ist. Bei Abfragen, Formularen und Berichten ist dies etwas einfacher – aber sehen Sie selbst!

Beispieldaten aus dem Feld einer Tabelle oder Abfrage beziehen

Nachdem wir ein wenig mit dem Format-Assistenten experimentiert haben, fiel uns auf, dass es eigentlich keinen richtigen Spaß macht, mit vorgegebenen Beispieldaten zu arbeiten beziehungsweise diese manuell anzupassen.

Viel cooler wäre es doch, wenn wir die Daten direkt aus dem zu formatierenden Feld beziehen könnten. Also fügen wir für die Auswahl der Beispieldaten noch eine Schaltfläche hinzu, mit der wir ein weiteres Formular öffnen können. Dieses soll alle Tabellen und Abfragen der aktuellen Datenbank zur Auswahl anbieten.

Nach der Auswahl der Tabelle oder Abfrage wollen wir dann die Felder der gewählten Datenquelle anbieten, um aus diesen das Feld mit den zu untersuchenden Daten auszuwählen.

Das Formular heißt frmDatenquellenUndFeldAuswaehlen und es enthält zwei Kombinationsfelder namens cboTabelleOderAbfrage und cboFeld. Zur Sicherheit sollen die Werte des gewählten Feldes auch noch in einem Listenfeld namens lstWerte angezeigt werden. Außerdem fügen wir zwei Schaltflächen namens cmdOK und cmdAbbrechen hinzu (siehe Bild 1).

Formular zum Auswählen der Daten, die in der Format-Vorschau angezeigt werden sollen

Bild 1: Formular zum Auswählen der Daten, die in der Format-Vorschau angezeigt werden sollen

Für diese hinterlegen wir jeweils eine Ereignisprozedur. Die Schaltfläche cmdOK soll das Formular ausblenden, damit wir die gewählten Daten von der aufrufenden Prozedur aus auswerten können:

Private Sub cmdOK_Click()
     Me.Visible = False
End Sub

Die Schaltfläche cmdAbbrechen soll das Formular einfach schließen:

Private Sub cmdAbbrechen_Click()
     DoCmd.Close acForm, Me.Name
End Sub

Öffnen des Formulars zum Auswählen der zu formatierenden Daten

Bevor wir uns die Funktion des Formulars frmDatenquelleUndFeldAuswaehlen genauer anschauen, werfen wir einen Blick auf die Schaltfläche cmdBeispielwerteEinlesen im aufrufenden Formular frmFormatassistent, mit der wir das Formular frmDatenquelleUndFeldAuswaehlen öffnen (siehe Bild 2).

Öffnen des Formulars frmDatenquelleUndFeldAktualisieren

Bild 2: Öffnen des Formulars frmDatenquelleUndFeldAktualisieren

Diese Prozedur heißt cmdBeispielwerteEinlesen_Click und ist in Listing 1 zu finden. Sie schließt zunächst sicherheitshalber das Formular frmDatenquelleUndFeldAuswaehlen, falls dieses noch geöffnet sein sollte. Der Hintergrund ist, dass nur beim erneuten Öffnen per DoCmd.Open auch die Parameter dieser Methode angewendet werden. Das Formular frmDatenquelleUndFeldAuswaehlen soll als modaler Dialog geöffnet werden. Außerdem wollen wir einige Informationen als Öffnungsargument übergeben.

Private Sub cmdBeispielwerteEinlesen_Click()
     Dim strForm As String
     Dim strTabelleOderAbfrage As String
     Dim strFeld As String
     strForm = "frmDatenquelleUndFeldAuswaehlen"
     On Error Resume Next
     DoCmd.Close acForm, strForm
     On Error GoTo 0
     DoCmd.OpenForm strForm, WindowMode:=acDialog, OpenArgs:=strObject & "|" & strControl & "|" & lngObjectType
     If IstFormularGeoeffnet(strForm) Then
         strTabelleOderAbfrage = Forms(strForm)!cboTabelleOderAbfrage
         strFeld = Forms(strForm)!cboFeld
         DoCmd.Close acForm, strForm
     End If
End Sub

Listing 1: Aufruf des Formulars frmDatenquelleUndFeldAuswaehlen

Wann immer wir hier mehr als eine Information übermitteln, können wir diese durch das Pipe-Zeichen (|) getrennt übergeben und diesen Ausdruck im aufgerufenen Formular wieder auseinandernehmen. In diesem Fall übergeben wir den Namen des Objekts (also Tabelle, Abfrage, Formular oder Bericht), den Namen des Feldes beziehungsweise Steuerelements und den Objekttyp.

Diese Informationen verarbeitet das Formular direkt in der Beim Öffnen-Ereignisprozedur – was dort geschieht, lesen Sie weiter unten. Wir schauen uns nun noch an, was nach der Eingabe der gewünschten Daten und dem Schließen des Formulars frmDatenquelleUndFeldAuswaehlen durch den Benutzer in der aufrufenden Prozedur noch geschieht. Diese prüft, ob das Formular noch geöffnet ist, was nur der Fall ist, wenn der Benutzer dort die OK-Schaltfläche betätigt hat. Ist das der Fall, aktualisiert die Prozedur die Daten im Unterformular und schließt dann das Formular frmDatenquelleUndFeldAuswaehlen.

Damit kommen wir nun zur Programmierung des Formulars frmDatenquellenUndFeldAuswaehlen.

Tabellen und Abfragen im Kombinationsfeld anzeigen

Für das Füllen der Kombinationsfelder mit den Tabellen oder Abfragen der Datenbank, von der aus wir den Assistenten aufgerufen haben, brauchen wir eine Liste der entsprechenden Elemente. Das ist insofern kompliziert, als das wir nicht einfach die Eigenschaft Datensatzherkunft auf die Tabelle MSysObjects einstellen können, die uns alle Tabellen und Abfragen liefern würde.

Damit würden wir nämlich auf die entsprechende Tabelle der Add-In-Datenbank zugreifen und nicht auf die der Host-Datenbank. Also erstellen wir in der gleich beschriebenen Ereignisprozedur, die durch das Ereignis Beim Öffnen des Formulars frmDatenquelleUndFeldAuswaehlen ausgelöst wird, ein Recordset auf Basis der entsprechenden Tabelle und weisen dieses dem Kombinationsfeld über seine Eigenschaft Recordset zu.

Als Datensatzherkunft für das Recordset des Steuerelements cboTabelleOderAbfrage verwenden wir die folgende Abfrage:

SELECT Name, Type FROM MSysObjects WHERE Type IN (1, 4, 5, 6) AND Not Name LIKE ''~*'' AND Not Name LIKE ''MSys*'' AND NOT Name LIKE ''USys*'' AND NOT Name LIKE ''f_*'' ORDER BY Name

Diese ermittelt die Namen und den Typ von Tabellen aller Typen (1, 4, 6) und von Abfragen (5). Außerdem schließt sie Systemobjekte und einige weitere Objekte aus, für die der Benutzer vermutlich nicht die Format-Eigenschaft einstellen möchte. Und die Abfrage liefert nicht nur den Objektnamen, sondern auch noch den Objekttyp des jeweiligen Datenbankobjekts.

Insgesamt sieht die Prozedur wie in Listing 2 aus. Die Prozedur schreibt den SQL-Ausdruck für den Zugriff auf die Tabelle MSysObjects in die Variable strSQL. Dann erstellt sie ein Recordset auf Basis dieser Abfrage und weist dieses anschließend der Eigenschaft Recordset des Kombinationsfeldes cboTabelleOderAbfrage zu.

Private Sub Form_Open(Cancel As Integer)
     Dim db As DAO.Database
     Dim rstTabellenUndAbfragen As DAO.Recordset
     Dim strSQL As String
     Set db = CurrentDb
     strSQL = "SELECT Name, Type FROM MSysObjects WHERE Type IN (1, 4, 5, 6) AND Not Name LIKE ''~*'' " _
         & "AND Not Name LIKE ''MSys*'' AND NOT Name LIKE ''USys*'' AND NOT Name LIKE ''f_*'' ORDER BY Name"
     Set rstTabellenUndAbfragen = db.OpenRecordset(strSQL, dbOpenDynaset)
     Set Me!cboTabelleOderAbfrage.Recordset = rstTabellenUndAbfragen
     If Not IsNull(Me.OpenArgs) Then
         strObject = Split(Me.OpenArgs, "|")(0)
         strControl = Split(Me.OpenArgs, "|")(1)
         intObjectType = Split(Me.OpenArgs, "|")(2)
     End If
     Select Case intObjectType
         Case acTable, acQuery
             Me!cboTabelleOderAbfrage = strObject
             FelderAktualisieren
             Me!cboFeld = strControl
             DatenAnzeigen
         Case acForm, acReport
             Me!cboTabelleOderAbfrage.SetFocus
             Me!cboTabelleOderAbfrage.Dropdown
     End Select
End Sub

Listing 2: Diese Prozedur wird beim Öffnen des Formulars frmDatenquellenUndFeldAuswaehlen aufgerufen.

Danach parst sie die mit dem Öffnungsargument übergebenen Daten. Dieses sieht beispielsweise wie folgt aus:

tblKunden|Eintrittsdatum|0

Diese Daten liest die Prozedur nun durch Aufteilen mit der Split-Funktion und anschließendes Abgreifen der Elemente des damit erzeugten Arrays ein und speichert sie in den Variablen strObject, strControl und intObjectType.

Dann prüft sie den Wert von intObjectType. Handelt es sich um eine Tabelle oder Abfrage (acTable oder acQuery), weist sie dem Kombinationsfeld cboTabelleOderAbfrage den entsprechenden Eintrag zu, also den Namen der mit dem Öffnungsargument übergebenen Tabelle oder Abfrage.

Dann ruft sie die Prozedur FelderAktualisieren auf, die wir gleich im Anschluss beschreiben.

Dem Kombinationsfeld cboFeld weist die Prozedur den Namen des übergebenen Feldes zu. Anschließend ruft die Prozedur die Routine DatenAnzeigen auf.

Im Falle eines Formulars oder Berichts wird einfach das Kombinationsfeld cboTabelleOderAbfrage aktiviert und aufgeklappt.

Aktualisieren der auszuwählenden Felder

Damit die Datensatzherkunft des zweiten Kombinationsfelds cboFeld das mit dem Öffnungsargument übergebene Feld überhaupt enthält, müssen diese nach der Festlegen des Eintrags im Kombinationsfeld cboTabelleOderAbfrage aktualisieren. Das erledigen wir durch den Aufruf der Prozedur FelderAktualisieren (siehe Listing 3).

Private Sub FelderAktualisieren()
     Dim db As DAO.Database
     Dim tdf As DAO.TableDef
     Dim qdf As DAO.QueryDef
     Dim fld As DAO.Field
     Me!cboFeld.RowSource = ""
     If Not Nz(Me!cboTabelleOderAbfrage, "") = 0 Then
         Set db = CurrentDb
         Select Case Me!cboTabelleOderAbfrage.Column(1)
             Case 1, 4, 6
                 Set tdf = db.TableDefs(Me!cboTabelleOderAbfrage)
                 For Each fld In tdf.Fields
                     Me!cboFeld.AddItem fld.Name
                 Next fld
             Case 5
                 Set qdf = db.QueryDefs(Me!cboTabelleOderAbfrage)
                 For Each fld In qdf.Fields
                     Me!cboFeld.AddItem fld.Name
                 Next fld
         End Select
     End If
End Sub

Listing 3: Diese Prozedur aktualisiert die im Kombinationsfeld cboFeld angezeigten Felder

Diese leert zunächst die Eigenschaft RowSource des Kombinationsfeldes cboFeld. Dann prüft sie, ob im Kombinationsfeld cboTabelleOderAbfrage überhaupt ein Objekt ausgewählt ist. Falls ja, prüft die Prozedur in einer Select Case-Bedingung, ob die zweite Spalte des Kombinationsfeldes, die zwar nicht angezeigt wird, aber über die Datensatzherkunft den Typ der Objekte enthält, dem Typ einer Tabelle oder Abfrage entspricht.

Im Falle einer Tabelle weist die Prozedur der Variablen tdf ein TableDefs-Objekt auf Basis der ausgewählten Tabelle zu. Anschließend durchläuft sie die Einträge der Fields-Auflistung des TableDef-Objekts in einer For Each-Schleife und fügt die Feldnamen mit der AddItem-Methode zum Kombinationsfeld cboFeld hinzu.

Damit wir dies überhaupt so machen können, stellen wir die Eigenschaft Herkunftstyp des Kombinationsfeldes auf Wertliste ein.

Ist der gewählte Eintrag hingegen eine Abfrage, erstellt die Prozedur ein QueryDef-Objekt und weist diesem das entsprechende Element der QueryDefs-Auflistung zu. Dann durchläuft sie wie bei der TableDefs-Auflistung die Felder des QueryDef-Objekts und fügt die Felder zum Kombinationsfeld cboFeld hinzu.

Feld der Datenquelle auswählen

Die oben vorgestellte Prozedur FelderAktualisieren, die direkt beim Start aufgerufen wird, soll auch dann ausgelöst werden, wenn der Benutzer eine andere Tabelle oder Abfrage aus dem Kombinationsfeld cboTabelleOderAbfrage aufruft. Daher hinterlegen wir für das Ereignis Nach Aktualisierung noch die folgende Ereignisprozedur:

Private Sub cboTabelleOderAbfrage_AfterUpdate()
     FelderAktualisieren
End Sub

Die Schaltfläche cmdOK soll nur aktiviert werden, wenn der Benutzer eine Tabelle oder Abfrage und ein Feld ausgewählt hat. Deshalb aktivieren wir diese nach der Auswahl eines der Einträge und wenn das Kombinationsfeld nicht leer ist:

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar