Wenn Sie Daten wie etwa Bestelldaten aus einer m:n-Beziehung in einem Formular verwalten, suchen Sie meist nach Bestellungen eines bestimmten Kunden, mit einem bestimmten Bestelldatum et cetera. Sie könnten aber auch einmal nach solchen Bestellungen suchen, die mindestens einen von mehreren Artikeln enthalten oder die gleich mehrere angegebene Artikel aufführen sollen. Solche eine Suche führen Sie am einfachsten in einem separaten Formular durch, das zur Suche geöffnet wird und die Ergebnisse zur Auswahl bereitstellt.
Die hier vorgestellte Lösung ist auf zwei Formulare aufgeteilt. Das erste Formular entspricht etwa dem von der Nordwind-Datenbank bekannten Bestellformular, das Kundendaten und Bestellinformationen anzeigt (s. Bild 1).
Bild 1: Bestellformular mit Filter-Funktion
Darüber hinaus bietet das Formular mit der Schaltfläche Bestellungen filtern die Möglichkeit, einen weiteren Dialog zu öffnen. Dieser erlaubt es, einen oder mehrere Artikel auszuwählen, nach denen die Bestellungen durchsucht werden. Der Dialog sieht wie in Bild 2 aus und bietet zwei wesentliche Funktionen. Zunächst legen Sie mit einer Optionsgruppe fest, ob Sie Bestellungen mit mindestens einem der nachfolgend angegebenen Artikel anzeigen möchten oder ob die Bestellungen alle gewählten Artikel enthalten müssen. Die Treffer werden gleich im Listenfeld rechts neben den Suchkriterien angezeigt. Mit einem Doppelklick auf einen der gefundenen Einträge zeigen Sie die entsprechende Bestellung im Bestellformular an.
Bild 2: Filterkriterien für Bestellungen zusammenstellen
Formular zur Anzeige der Bestellungen
Dieses Formular enthält keine besonderen Techniken. Das Hauptformular frmBestellungen enthält als Datenherkunft eine Abfrage, die auf der Tabelle tblBestellungen basiert. Das Unterformular sfmBestelldetails liefert die zur jeweiligen Bestellung gehörenden Daten aus der Tabelle tblBestelldetails. Die Schaltfläche cmdOK schließt das Formular, die Schaltfläche cmdBestellungenFiltern öffnet den Dialog zum Zusammenstellen des Filters:
Private Sub cmdBestellungenFiltern_Click() DoCmd.OpenForm "frmFilterkriterien" End Sub
Das Filterformular
Das Formular frmFilterkriterien sieht im Entwurf wie in Bild 3 aus. Zur Eingabe der Filterkriterien stehen zwei Steuerelemente zur Verfügung. Das erste ist die Optionsgruppe ogrArtikelfilter mit den beiden Optionen Oder (Wert 1) und Und (Wert 2) und dem Standardwert 1. Das zweite Steuerelement ist ein Listenfeld namens lstArtikelfilter. Es enthält als Datensatzherkunft den folgenden Ausdruck:
Bild 3: Das Formular frmFilterkriterien in der Entwurfsansicht
SELECT ArtikelID, Artikelname FROM tblArtikel ORDER BY Artikelname;
Dadurch zeigt es alle Artikelnamen in alphabetischer Reihenfolge an. Damit nur die Artikelnamen erscheinen und nicht die ArtikelID, erhalten die beiden Eigenschaften Spaltenanzahl und Spaltenbreiten die Werte 2 und 0cm.
Der Benutzer soll einen oder mehrere Werte dieses Listenfeldes markieren, daher stellen Sie die Eigenschaft Mehrfachauswahl auf Einfach ein (oder Erweitert, je nachdem, was Ihnen angenehmer ist).
Datensatzherkunft des Ergebnislistenfeldes
Das Ergebnislistenfeld zeigt beim Öffnen des Formulars die mit der Abfrage qryBestellungenBestelldetails ermittelten Daten an (s. Bild 4). Diese Abfrage führt Daten aus den Tabellen tblBestellungen, tblBestelldetails und tblArtikel zusammen und sortiert diese aufsteigend nach dem Bestelldatum.
Bild 4: Die Abfrage qryBestellungenBestelldetails dient als Datensatzherkunft des Listenfeldes lstBestellungen.
Auslösen der Aktualisierung der gefundenen Bestellungen
Da es mehr als ein Steuerelement gibt, das die Datensatzherkunft des Listenfeldes lstBestellungen ändert, wurden die Codezeilen zum Filtern der Bestellungen in eine eigene Prozedur ausgegliedert. Diese heißt Bestellungen filtern und wird durch zwei Ereignisse ausgelöst. Das erste ist das Aktualisieren der Optionsgruppe ogrArtikelfilter. Die dazugehörige Ereignisprozedur sieht so aus:
Private Sub ogrArtikelfilter_AfterUpdate() BestellungenFiltern End Sub
Das zweite Ereignis ist das ändern der Auswahl im Listenfeld lstArtikelfilter:
Private Sub lstArtikelfilter_AfterUpdate() BestellungenFiltern End Sub
Gefilterte Bestellungen ermitteln
Die Prozedur BestellungenFiltern im Klassenmodul des Formulars frmFilterkriterien erledigt die Hauptarbeit (s. Listing 1). Die Prozedur durchläuft zunächst alle ausgewählten Einträge des Listenfeldes lstArtikelfilter. Dies geschieht innerhalb einer For…Next-Schleife mit der Laufvariablen i. Die Anzahl der zu durchlaufenden Elemente wird über die Eigenschaft Count der Auflistung ItemsSelected des Listenfeldes ermittelt.
Listing 1: Zusammenstellen der Datensatzherkunft nach dem Festlegen von Filterkriterien
Private Sub BestellungenFiltern() Dim i As Integer Dim lngIndex As Long Dim lngArtikelID As Long Dim strFilter As String Dim strSQL As String Dim intAnzahl As Integer For i = 0 To Me!lstArtikelfilter.ItemsSelected.Count - 1 lngIndex = Me!lstArtikelfilter.ItemsSelected(i) lngArtikelID = Me!lstArtikelfilter.ItemData(lngIndex) strFilter = strFilter & " OR ArtikelID = " & lngArtikelID intAnzahl = intAnzahl + 1 Next i If Len(strFilter) > 0 Then strFilter = Mid(strFilter, 4) strSQL = "SELECT DISTINCT BestellungID, Bestelldatum, Firma, Kontaktperson " _ & "FROM qryBestellungenBestelldetails" If Me!ogrArtikelfilter = 1 Then Me!lstBestellungen.RowSource = strSQL & " WHERE " & strFilter Else If Not intAnzahl = 0 Then strSQL = strSQL & " WHERE (" & strFilter & ") GROUP BY BestellungID, " _ & "Bestelldatum, Firma, Kontaktperson HAVING Count(BestellungID)=" _ & intAnzahl & ";" Me!lstBestellungen.RowSource = strSQL End If End If Else Me!lstBestellungen.RowSource = "SELECT DISTINCT BestellungID, Bestelldatum, Firma, " _ & "Kontaktperson FROM qryBestellungenBestelldetails" End If End Sub
Die erste Zeile innerhalb der Schleife ermittelt den Index des jeweiligen Eintrags der Auflistung ItemsSelected und speichert ihn in der Variablen lngIndex. Wenn beispielsweise als erstes markiertes Element der dritte Eintrag erkannt wird, enthält lngIndex den Wert 2 (die Indizes sind 0-basiert). Die ItemData-Eigenschaft mit diesem Index-Wert als Parameter liefert den Wert der gebundenen Spalte des Listenfeldes, also den Wert des Feldes ArtikelID, und speichert diesen in einer weiteren Variablen namens lngArtikelID. Für jeden markierten Eintrag des Listenfeldes wird nun eine OR-Klausel an die Zeichenkette strFilter angehängt, die etwa wie folgt aussieht:
OR ArtikelID = 12
Außerdem wird die Zählervariable intAnzahl um 1 erhöht. Stellt die Prozedur nach dem Verlassen der For…Next-Schleife fest, dass mindestens ein Eintrag markiert und somit die Länge der in der Variablen strFilter gespeicherten Zeichenkette größer als 0 ist, wird der If-Teil der folgenden If…Then…Else-Bedingung abgearbeitet.
Falls nicht, weist die Prozedur dem Listenfeld lstBestellungen erneut die bereits beim Öffnen des Formulars verwendete Abfrage qryBestellungenBestelldetails als Wert der Eigenschaft RowSource (Datensatzherkunft) zu – mit dem Unterschied, dass nur die vier Felder BestellungID, Bestelldatum, Firma und Kontaktperson ausgegeben werden. Außerdem wird durch Verwendung des Schlüsselworts DISTINCT sichergestellt, dass jede Bestellung nur einmal aufgeführt wird und nicht für jeden Artikel jeweils einmal.
Ist jedoch ein Filterausdruck vorhanden, wird es interessant. Zunächst einmal wird das führende OR mit der Mid-Funktion abgeschnitten, damit aus einem Ausdruck wie
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