Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.
Suchen mit der clsFlexSearch-Klasse
Die Klasse clsFlexSearch lässt sich einfach in Formulare integrieren und fügt einem einfachen Textfeld umfassende Suchmöglichkeiten hinzu. Wie Sie diese Suche implementieren, erfahren Sie im Beitrag Flexible Suche in Formularen (www.access-im-unternehmen.de/965). Der vorliegende Beitrag erläutert die Klasse clsFlexSearch und stellt den Code vor, damit Sie diesen nachvollziehen und ihn gegebenenfalls an Ihre eigenen Bedürfnisse anpassen können.
Alles in einer Klasse
Die Klasse clsFlexSearch bietet nicht nur eine praktische Suchfunktion, sondern Sie ist außerdem auch noch ganz leicht zu implementieren.
Der Grund ist, dass der komplette Code in einer einzigen Klasse gekapselt ist und Sie dem Formular, das Sie mit der Funktion ausstatten möchten, lediglich einige Zeilen VBA-Code hinzufügen müssen.
Die Klasse hat die Aufgabe, ein Textfeld mit einer Suchfunktion zu versehen (s. Bild 1). Der Benutzer gibt dort das Suchkriterium ein und die in der Klasse enthaltenen Ereignisprozeduren liefern die Funktionen dazu:
Bild 1: Die Klasse clsFlexSearch in Aktion- die automatische Ergänzung der Eingabe des Benutzers bezüglich der zu durchsuchenden Feldnamen und
- die Funktion, die den eingegebenen Ausdruck parst und eine entsprechende Where-Klausel formuliert und zurückgibt.
Die Klasse clsFlexSearch
Um die Klasse anzulegen, erstellen Sie im VBA-Editor über Einfügen|Klassenmodul ein neues Klassenmodul und speichern es unter dem Namen clsFlexSearch.
Die Klasse verwendet insgesamt vier Member-Variablen, denen der Benutzer vom Klassenmodul des Formulars aus die entsprechenden Eigenschaftswerte zuweist. Diese Member-Variablen werden wie folgt im Kopf des Klassenmoduls clsFlexSearch deklariert:
Private m_Suchabfrage As String
Private m_PKFeld As String
Private m_PKFeldEinschliessen As Boolean
Private WithEvents m_Suchfeld As TextBox
Eigenschaften zuweisen
Die in diesen vier Variablen gespeicherten Werte sollen über öffentliche Eigenschaften der Implementierung der Klasse clsFlexSearch zugewiesen werden, also etwa so:
With objFlexSearch
.Suchabfrage = "qryArtikelsuche"
.PKFeld = "ArtikelID"
.PKFeldEinschliessen = False
Set .Suchfeld = Me!txtSucheNach
End With
Diese Eigenschaften zum Entgegennehmen der Werte für die Member-Variablen programmieren wir in der Klasse clsFlexSearch als Public Property Let- beziehungsweise Public Property Set-Prozeduren. Die erste sieht wie in Listing 1 aus und nimmt als Parameter einen Wert entgegen, der nach dem Zuweisen in die Variable m_Suchabfrage eingetragen wird.
Public Property Let Suchabfrage(strSuchabfrage As String)
m_Suchabfrage = strSuchabfrage
End Property
Listing 1: Öffentliche Eigenschaft für die Angabe der Suchabfrage
Für Wert-Variablen etwa vom Datentyp String verwenden wir das Schlüsselwort Let, später für Objektvariablen das Schlüsselwort Set.
Die Public Property Let-Prozedur PKFeld aus Listing 2 erwartet den Namen des Primärschlüsselfeldes und weist diesen der Membervariablen m_PKFeld zu.
Public Property Let PKFeld(strPKFeld As String)
m_PKFeld = strPKFeld
End Property
Listing 2: Öffentliche Eigenschaft für die Angabe des Primärschlüsselfeldes
Ähnlich arbeitet die Public Property Let-Prozedur PKFeldEinschliessen. Die an diese Eigenschaft übergebene Variable legt fest, ob der Name des Primärschlüsselfelds im Such-Textfeld automatisch ergänzt und ob es bei der Suche über alle Felder berücksichtigt werden soll (s. Listing 3).
Public Property Let PKFeldEinschliessen(bolPKFeldEinschliessen As Boolean)
m_PKFeldEinschliessen = bolPKFeldEinschliessen
End Property
Listing 3: Hiermit legen Sie fest, ob der Primärschlüssel für die Suche berücksichtigt wird.
Interessant wird es bei der Public Property Set-Prozedur Suchfeld. Diese nimmt einen Verweis auf das Textfeld entgegen, das zur Eingabe der Suchbegriffe verwendet werden soll.
Die Prozedur speichert diesen Verweis in der Membervariablen m_Suchfeld, welches den Datentyp Textbox aufweist und mit dem Schlüsselwort WithEvents deklariert wurde.
Auf diese Weise können Sie, auch wenn das Textfeld gar kein Objekt der aktuellen Klasse ist, in dieser Klasse auf seine Ereignisse reagieren. Dazu tragen wir für die den relevanten Ereignissen entsprechenden Eigenschaften jeweils den Wert [Event Procedure] ein – hier für die Eigenschaften OnKeyUp und OnKeyDown (s. Listing 4).
Public Property Set Suchfeld(txtSuchfeld As TextBox)
Set m_Suchfeld = txtSuchfeld
With m_Suchfeld
.OnKeyDown = "[Event Procedure]"
.OnKeyUp = "[Event Procedure]"
End With
End Property
Listing 4: Zuweisen des Such-Textfeldes
Auf die entsprechenden Ereignisse Bei Taste ab und Bei Taste auf reagieren wir, um bei der Eingabe von Zeichen erstens zu prüfen, ob hier eine automatische Vervollständigung angewendet werden muss, und zweitens, um auf die Tab-Taste und das Zeichen Doppelpunkt (:) zu reagieren.
Beides soll den als Autovervollständigungs-Wert angegebenen Ausdruck bestätigen und einen Doppelpunkt hinten anfügen, damit der Benutzer hier den Vergleichsausdruck eintragen kann.
Beim Herunterdrücken einer Taste
Nun müssen wir die Ereignisprozedur programmieren, die beim Herunterdrücken einer Taste im Suchen-Textfeld ausgelöst wird. Die Prozedur sieht wie in Listing 5 aus und liefert mit KeyCode einen der gedrückten Taste entsprechenden Integer-Wert sowie mit Shift einen Wert, der angibt, ob gleichzeitig die Umschalt-, die Alt- oder die Strg-Taste gedrückt wurde.
Private Sub m_Suchfeld_KeyDown(KeyCode As Integer, Shift As Integer)
Dim intSelStart As Integer
Dim intSelLength As Integer
Dim intStarttemp As Integer
Dim i As Integer
Dim intLenTemp As Integer
Dim strFeldTemp As String
Dim strSuche As String
intKeycode = KeyCode
Select Case intKeycode
Case 9, 190
If intKeycode = 190 And Not Shift = acShiftMask Then
Exit Sub
End If
KeyCode = 0
strSuche = m_Suchfeld.Text
intSelStart = m_Suchfeld.SelStart
intSelLength = m_Suchfeld.SelLength
If Not ArrayGefuellt(strSuchfelder) Then
SuchfelderEinlesen
End If
intStarttemp = InStrRev(strSuche, " ", intSelStart + intSelLength) + 1
strFeldTemp = Mid(strSuche, intStarttemp, intSelStart + intSelLength)
If Len(strFeldTemp) > 0 Then
intLenTemp = Len(strFeldTemp)
For i = LBound(strSuchfelder) To UBound(strSuchfelder)
If strFeldTemp = Left(strSuchfelder(i), intLenTemp) Then
m_Suchfeld.Text = Left(m_Suchfeld.Text, intSelStart + intSelLength - 1) _ & Mid(strSuchfelder(i), intLenTemp) & ":" _ & Mid(m_Suchfeld.Text, intSelStart + intSelLength + 1)
m_Suchfeld.SelStart = _ intSelStart + intSelLength + Len(strSuchfelder(i)) - intLenTemp + 1
Exit For
End If
Next i
End If
Case 13
Suchen m_Suchfeld.Text
KeyCode = 0
Case Else
Debug.Print intKeycode
End Select
End Sub
Listing 5: Ereignisprozedur, die bei Herunterdrücken einer Taste im Suchen-Textfeld ausgelöst wird
Die Prozedur speichert zunächst den KeyCode in der Variablen intKeyCode, die wir im Kopf des Klassenmoduls wie folgt deklarieren:
Dim intKeycode As Integer
Dies ist nötig, weil wir den KeyCode in einigen Fällen auch noch in der später aufgerufenen Ereignisprozedur m_Suchfeld_KeyUp benötigen, diese aber in m_Suchfeld_KeyDown auf den Wert 0 setzen, damit die eigentliche Wirkung dieses Tastendrucks unterdrückt wird.
Die folgende Select Case-Bedingung prüft einige Werte für intKeyCode. Der erste Zweig reagiert auf die Werte 9 und 190. 9 entspricht der Tab-Taste, 190 dem Doppelpunkt.
Eigentlich entspricht 190 der Taste, auf der sich der Punkt und der Doppelpunkt befinden, aber auf den Punkt wollen wir nicht reagieren. Also verlassen wir die Prozedur, wenn der zweite Parameter, Shift, nicht den Wert 1 (oder acShiftMask) enthält.
In diesem Fall stellen wir KeyCode auf den Wert 0 ein, da etwa das Betätigen der Tab-Taste sonst zum Verlassen des Textfeldes führen würde. Die Prozedur speichert den aktuellen Inhalt des mit m_Suchfeld referenzierten Such-Textfeldes in der Variablen strSuche. Die Variable intSelStart nimmt die aktuelle Position der Einfügemarke auf, die Variable intSelLength die Länge des aktuell markierten Textes.
Nun benötigen wir eine Liste aller Suchfelder, also derjenigen Felder, die in der für die Eigenschaft Suchabfrage angegebenen Abfrage enthalten sind.
Der Performance halber wollen wir diese nicht jedes Mal neu aus der Definition der Abfrage abrufen, deshalb speichern wir diese einmalig in einem Array namens strSuchfelder.
Um dieses nur einmal zu füllen, prüfen wir zunächst mithilfe der Funktion ArrayGefuellt, ob das Array strSuchfelder bereits gefüllt ist. Diese Funktion erläutern wir im Detail im Beitrag Mit Arrays arbeiten (www.access-im-unternehmen.de/963).
Die Variable strSuchfelder deklarieren wir übrigens wie folgt im Kopf des Klassenmoduls clsFlexSearch:
Dim strSuchfelder() As String
Wenn das Array noch nicht gefüllt ist, liest die Prozedur SuchfelderEinlesen die Felder der unter m_Suchabfrage angegebenen Abfrage in das Array strSuchfelder ein (s. Listing 6). Die Prozedur öffnet ein QueryDef-Objekt auf Basis der angegebenen Abfrage und durchläuft in einer For Each-Schleife alle Felder dieser Abfrage. Dabei prüft die Prozedur, ob es sich bei dem aktuellen Feld um das als Primärschlüssel angegebene Feld handelt und dieses gleichzeitig für die Suche berücksichtigt werden soll.
Private Sub SuchfelderEinlesen()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim fld As DAO.Field
Dim i As Integer
Set db = CurrentDb
Set qdf = db.QueryDefs(m_Suchabfrage)
For Each fld In qdf.Fields
If Not (fld.Name = m_PKFeld And m_PKFeldEinschliessen = False) Then
ReDim Preserve strSuchfelder(qdf.Fields.Count) As String
strSuchfelder(i) = fld.Name
i = i + 1
End If
Next fld
End Sub
Listing 6: Einlesen von Suchfeldern in ein Array
Ist dies der Fall oder handelt es sich um eines der übrigen Felder, fügt die Prozedur den Namen des Feldes zum Array hinzu, wobei zuvor die Anzahl der zulässigen Elemente angepasst wird.
Die Prozedur ermittelt dann ausgehend von der aktuellen Position der Einfügemarke die Position des ersten Leerzeichens links von der Einfügemarke und speichert diese in der Variablen intStartTemp. Sollte hierbei kein Leerzeichen gefunden werden, liefert die InStrRev-Funktion den Wert 0. In jedem Fall addiert diese Zeile den Wert 1 zum Ergebnis.
In strFeldTemp landet dann die Zeichenkette, die sich zwischen dieser Position und der aktuellen Position der Einfügemarke befindet (inklusive Markierung, falls vorhanden).
Enthält strFeldTemp nun einen Wert (Len(strFeldTemp) > 0), beginnt die weitere Verarbeitung. Die Variable intLenTemp wird nun mit der Länge des in strFeldTemp gespeicherten Ausdrucks gefüllt.
In einer For...Next-Schleife durchläuft die Prozedur alle Einträge des Arrays strSuchfelder, also alle Feldnamen der Suchabfrage. Darin prüft die Prozedur, ob der in strFeldTemp gespeicherte Ausdruck mit den ersten intLenTemp Zeichen des Feldnamens übereinstimmt.
Wenn strFeldTemp also nun den Ausdruck Art enthält, weil der Benutzer gerade das Feld Artikelname eintippen möchte, vergleicht die Prozedur diesen Ausdruck jeweils mit den ersten drei Zeichen der in der Variablen strSuchfelder gespeicherten Feldnamen. Stößt die Prozedur so auf das Feld Artikelname, wird der Teil innerhalb der If...Then-Bedingung ausgeführt. Hier trägt die Prozedur einen Ausdruck in die Eigenschaft Text des Suchen-Textfeldes ein, der aus den folgenden Elementen besteht:
- Inhalt des Such-Textfeldes bis zur Einfügemarke und
- den Teil des gefundenen Feldnamens, der noch nicht eingegeben wurde (in diesem Beispiel Artikelname ohne die ersten drei Buchstaben Art, also ikelname) und
- den Doppelpunkt.
Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.