Wenn der Kunde anruft, möchten Sie schnell den entsprechenden Kundendatensatz auf dem Bildschirm haben. Dazu stellen wir im vorliegenden Beitrag ein Formular samt Unterformular zusammen, mit denen die gewünschten Daten schnell ermittelt werden können. Im Hauptformular bieten wir einige Suchfunktionen an, im Unterformular liefern wir die den Suchkriterien entsprechenden Daten in der Datenblattansicht. Außerdem soll das Formular die Möglichkeit bieten, den gefundenen Kundendatensatz im Detailformular zu öffnen, damit wir auch noch die Bestellungen des Kunden einsehen können.
Unterformular für die Kundenliste
Bevor wir beginnen, das Hauptformular zu programmieren, legen wir zunächst das Unterformular an. Dann können wir dieses gleich im Anschluss direkt zum Hauptformular hinzufügen.
Das neue Unterformular soll sfmKundenuebersicht heißen und standardmäßig die Daten der Tabelle tblKunden anzeigen. Deshalb stellen wir seine Eigenschaft Datensatzquelle auf diese Tabelle ein. Anschließend können wir alle Felder der Feldliste in den Detailbereich des Formulars ziehen. Gegebenenfalls lassen wir das Primärschlüsselfeld ID weg, da dieses nur zum Herstellen von Beziehungen dient und keine geschäftliche Funktion hat.
Damit das Formular die Daten in der Datenblattansicht anzeigt, legen wir für die Eigenschaft Standardansicht noch den Wert Datenblatt fest (siehe Bild 1). Damit können wir die Arbeiten am Unterformular bereits beenden und dieses schließen.
Bild 1: Entwurf des Unterformulars sfmKundenuebersicht
Hauptformular erstellen
Anschließend erstellen wir das Hauptformular und speichern dieses direkt unter dem Namen frmKundenuebersicht. Diesem weisen wir keine Datensatzquelle zu, weil es selbst keine Daten anzeigen soll – diese liefert allein das Unterformular. Im Hauptformular wollen wir nur Steuerelemente zum Durchsuchen der Kundendaten und zum Öffnen von Detaildatensätzen bereitstellen. Daher benötigen wir im Hauptformular auch nicht die Steuerelemente zum Navigieren in Datensätzen und stellen daher einige Eigenschaften ein. Die Eigenschaften Navigationsschaltflächen, Datensatzmarkierer, Bildlaufleisten und Trennlinien setzen wir auf den Wert Nein, die Eigenschaft Automatisch zentrieren auf Ja.
Dann ziehen wir aus dem Navigationsbereich das Unterformular sfmKundenuebersicht in den Detailbereich des Formularentwurfs von frmKundenuebersicht. Das Bezeichnungsfeld des Unterformular-Steuerelements entfernen wir, da wir ja wissen, dass dieses Kundendaten anzeigt.
Damit das Unterformular beim Vergrößern des Hauptformulars ebenfalls vergrößert wird, stellen wir seine Eigenschaften Horizontaler Anker und Vertikaler Anker jeweils auf Beide ein.
Wenn wir oben und unten ein wenig Platz für die Steuerelemente zum Suchen und zum Aufrufen der Anzeige der Kundendetails lassen, sieht der Entwurf nun wie in Bild 2 aus.
Bild 2: Haupt- und Unterformular im Entwurf
Steuerelemente zum Filtern der Kunden hinzufügen
Damit kommen wir zu den Steuerelementen, mit denen wir die Filterkriterien für die anzuzeigenden Kunden eingeben wollen. Diese platzieren wir wie in Bild 3 im Bereich über dem Unterformular. Die Steuerelemente heißen:
Bild 3: Hinzufügen der Steuerelemente zum Filtern der Kundendatensätze
- txtFilterKundennummer
- txtFilterFirma
- txtFilterVorname
- txtFilterNachname
- txtFilterStrasse
- txtFilterPLZ
- txtFilterOrt
- txtFilterEMail
Das Filtern wollen wir einfach und schnell realisieren: Jede Eingabe in eines der Filterfelder soll unmittelbar die gefilterten Daten anzeigen. Außerdem soll immer im kompletten zu filternden Feld nach dem im jeweiligen Filterfeld eingegebenen Text gesucht werden. Sprich: Wenn der Benutzer im Feld txtFilterKundennummer den Wert 1 eingibt, sollen alle Datensätze angezeigt werden, die an beliebiger Stelle im Feld Kundennummer den Wert 1 enthalten.
Das heißt auch, dass wir für jedes der Steuerelemente zur Eingabe der Filterkriterien das Ereignis Bei Änderung implementieren müssen. Mit diesem rufen wir dann jeweils eine weitere Prozedur auf, welche die jeweiligen Werte der Filter-Textfelder ausliest und ein entsprechendes SQL-Kriterium zusammenstellt.
Unterschiedliche Eigenschaften zum Ermitteln der Vergleichskriterien
Das Problem dabei ist, dass wir für die Inhalte der Filter-Textfelder auf unterschiedliche Eigenschaften zugreifen müssen. Normalerweise greifen wir einfach auf die Value-Eigenschaft zu. Diese können wir allerdings nicht nutzen, wenn wir während der Eingabe auf den Inhalt im aktuellen Textfeld zugreifen wollen. Der Grund ist, dass die Value-Eigenschaft erst mit dem aktuell im Textfeld enthaltenen Wert gefüllt wird, wenn der Benutzer die Eingabe bestätigt – beispielsweise, indem er das Textfeld verlässt und den Fokus auf das nächste Textfeld verschiebt. In diesem Fall lässt sich der aktuell im Textfeld dargestellte Text nur mit der Eigenschaft Text auslesen.
Wir müssen also zumindest für das aktuelle Textfeld auf die Text-Eigenschaft zugreifen und können nicht die Value-Eigenschaft nutzen. Aber warum ist das überhaupt ein Problem? Können wir nicht einfach auf den Inhalt aller Felder über die Text-Eigenschaft zugreifen? Das wiederum gelingt nicht, weil man nur für das Textfeld auf die Text-Eigenschaft zugreifen kann, das aktuell den Fokus hat.
Wir müssen also den Inhalt des aktuell bearbeiteten Textfeldes mit der Text– und den der übrigen Textfelder mit der Value-Eigenschaft abfragen und prüfen, ob diese Kriteriumsausdrücke enthalten. Wobei die Value-Eigenschaft wiederum die Standardeigenschaft der TextBox-Klasse ist, weshalb wir diese gar nicht angeben müssen. Statt Me!txtFilterKundennummer.Value können wir einfach Me!txtFilterKundennummer schreiben.
Prozedur zum Ermitteln des Filterkriteriums für das Unterformular
Wir legen also zunächst für jedes der Filter-Textfelder eine Ereignisprozedur für das Ereignis Bei Änderung an. Diese enthält für alle Filter-Textfelder den Aufruf einer weiteren Prozedur namens KundenFiltern – wie hier am Beispiel der Prozedur txtFilterEMail zu sehen:
Private Sub txtFilterEMail_Change() KundenFiltern End Sub
Einfache Variante zum Zusammensetzen des Filterkriterums
Die Prozedur zum Zusammenstellen eines Filterausdrucks für das Unterformular können wir geradlinig und einfach aufbauen oder auch auf den ersten Blick etwas komplizierter, dafür aber flexibler. Wir schauen uns beide Varianten an. Die erste finden Sie in Listing 1.
Private Sub KundenFiltern() Dim strFilter As String If Me!txtFilterKundennummer Is Me.ActiveControl Then If Not Len(Me!txtFilterKundennummer.Text) = 0 Then strFilter = strFilter & " AND Kundennummer LIKE ''*" & Me!txtFilterKundennummer.Text & "*''" End If Else If Not Len(Me!txtFilterKundennummer.Value) = 0 Then strFilter = strFilter & " AND Kundennummer LIKE ''*" & Me!txtFilterKundennummer.Value & "*''" End If End If If Me!txtFilterFirma Is Me.ActiveControl Then If Not Len(Me!txtFilterFirma.Text) = 0 Then strFilter = strFilter & " AND Firma LIKE ''*" & Me!txtFilterFirma.Text & "*''" End If Else If Not Len(Me!txtFilterFirma.Value) = 0 Then strFilter = strFilter & " AND txtFilterFirma LIKE ''*" & Me!txtFilterFirma.Value & "*''" End If End If ''... If Not Len(strFilter) = 0 Then strFilter = Mid(strFilter, 5) With Me!sfmKundenuebersicht.Form .Filter = strFilter .FilterOn = True End With Else Me!sfmKundenuebersicht.Form.Filter = "" End If End Sub
Listing 1: Prozedur zum Einstellen des Filters für das Unterformular, einfache Version
Diese Version verwendet eine Variable namens strFilter, um den Filterausdruck darin zusammenzustellen. Sie prüft für jedes der Filter-Textfelder, ob es sich dabei um das aktuelle Steuerelement handelt, also das Steuerelement, das aktuell den Fokus enthält. Das dient der Unterscheidung, ob wir die Text– oder die Value-Eigenschaft zum Ermitteln des jeweils in dem Steuerelement enthaltenen Textes verwenden müssen.
Um herauszufinden, ob wir es bei dem aktuellen Steuerelement mit dem aktiven Steuerelement zu tun haben, vergleichen wir dieses mit dem Verweis auf das Steuerelement, das wir mit der Eigenschaft ActiveControl des Formulars ermitteln können. Sind beide gleich, handelt es sich um das aktive Steuerelement, sonst nicht. Ist das Steuerelement das aktive Steuerelement und ist dieses nicht leer, lesen wir den Inhalt mit der Text-Eigenschaft und stellen damit einen Ausdruck wie den folgenden zusammen:
AND Kundennummer LIKE ''*Vergleichsausdruck*''
Vergleichsausdruck entspricht dabei dem Inhalt des jeweiligen Textfeldes. Falls es sich bei dem aktuell untersuchten Steuerelement nicht um das aktive Steuerelement handelt, verwenden wir für den gleichen Ausdruck den Inhalt der Value-Eigenschaft des Textfeldes.