Eine der bekanntesten Tastenkombinationen dürfte Strg + F zum Aktivieren der Suchfunktion sein. Der Windows Explorer hat sie, die Internet Browser verwenden sie einheitlich und die Office-Anwendungen greifen darauf zurück. Haben Sie Ihre Anwendungen auch schon damit ausgestattet Nein Na, dann wird es aber höchste Zeit! Spendieren Sie den Benutzern diesen Shortcut und zeigen Sie die richtige Suche für den aktuellen Kontext an.
Ziel dieser Lösung
In einer Access-Anwendung braucht man, wie in anderen Anwendungen auch, hier und da eine Suchfunktion. Normalerweise bezieht sich diese Suche auf die in einem Formular angezeigten Daten und soll das Durchsuchen der enthaltenen Felder ermöglichen.
Die für die Suche notwendigen Elemente sind dabei meist Teil des Formulars selbst; manchmal öffnet sich auch ein extra Formular mit den Feldern zur Eingabe der Suchkriterien und gegebenenfalls einer Ergebnisliste.
Dieser Beitrag stellt eine Suchfunktion vor, die Sie von beliebigen Formularen aus aufrufen können und deren Inhalt Sie größtenteil selbst konfigurieren können. Der Aufruf soll über die bekannte Tastenkombination Strg + F erfolgen und einen Suchdialog anzeigen, der die zu durchsuchenden Felder des zum Zeitpunkt des Aufrufs geöffneten Formulars anzeigt.
Es soll aber auch möglich sein, nach anderen Elementen zu suchen, als nach solchen, die das aktuelle Formular anzeigt – also beispielsweise nach Artikeln -, während das Kundenformular sichtbar ist. Und für alle Fälle liefert die Lösung auch die Möglichkeit, in allen festgelegten Tabellen nach Elementen zu suchen.
Wichtig ist hier natürlich eine hohe Konfigurierbarkeit. Dies bezieht sich vor allem auf die folgenden Punkte:
- Sie legen die Tabellen fest, in denen gesucht werden soll.
- Sie definieren die Felder, die in die Suche einbezogen werden.
- Sie stellen die Formulare ein, die beim Anklicken eines der Suchergebnisse geöffnet werden und das ausgewählte Ergebnis anzeigen sollen.
- Außerdem soll die Suche verschiedene Tabellen oder auch alle Tabellen durchforsten können – je nachdem, von wo sie aufgerufen wurde. Geschieht dies beispielsweise vom Kundenformular aus, soll sie standardmäßig die Kunden durchsuchen; ist gerade kein Formular geöffnet, durchsucht sie alle angegebenen Tabellen oder der Benutzer stellt selbst ein, welche Daten für die Suche verwendet werden sollen.
Der Benutzer sieht von diesen Konfigurationsmöglichkeiten nichts – er soll lediglich die Suche nutzen können.
Suche vorbereiten
Die Suche bereiten Sie als Entwickler mit dem Formular frmGlobalSearchOptions vor. Dieses sieht wie in Bild 1 aus und zeigt jeweils die Definition einer Suche in einem Datensatz an. Gleichzeitig können Sie hier auch festlegen, wie die Daten der Datenherkunft dieser Suche in einer Suche über alle Daten angezeigt werden sollen.
Bild 1: Konfigurationsformular für die globale Suche
Schauen wir uns die Suchdefinition aus Bild 1 genauer an. Die im Konfigurationsformular angezeigte Suche wird in fünf Bereichen definiert. Der erste Bereich erwartet die Eingabe eines Titels, der das gesuchte Element umschreibt (hier Artikel), die Tabelle oder Abfrage, aus der die Daten stammen (tblArtikel) und das Primärschlüsselfeld dieser Tabelle (ArtikelID).
Die nächsten sechs Felder im zweiten Bereich enthalten sämtliche Parameter der DoCmd.OpenForm-Methode. Damit können Sie genau festlegen, welches Formular angezeigt wird, wenn der Benutzer die Details zu einem Suchergebnis des Typs Artikel sehen möchte und wie dieses geöffnet werden soll. Interessant ist die Möglichkeit, etwa für den Parameter WhereCondition Platzhalter wie [PKID], [PKIDValue] und [Title] einzufügen. Diese werden zur Laufzeit durch den Primärschlüsselnamen, den Primärschlüsselwert und den weiter oben im Formular angegebenen Titel ersetzt. Anders wäre es auch kaum denkbar, ein Formular zu öffnen, das den in der globalen Suche ausgewählten Datensatz anzeigt.
Der untere Bereich enthält nur ein Feld, das einen Ausdruck für die Ausgabe im Suchergebnis der globalen Suche erwartet. Wie erwähnt, können Sie, wenn das Suchformular nicht in einem bestimmten Kontext geöffnet wurde, eine globale Suche über alle in der Suchkonfiguration angegebenen Tabellen durchführen. Nun bestehen die Suchergebnisse der einzelnen Suchen, wie etwa nach Artikeln oder Kunden, aus verschiedenen Feldern, die auch noch eine unterschiedliche Anzahl aufweisen können. Damit das Suchergebnis einer globalen Suche dennoch aussagekräftig ist, soll es nur zwei Spalten enthalten, von denen die erste den weiter oben angegebenen Titel liefert und damit einen Hinweis auf die Tabelle, aus der die Datensätze stammen, und die zweite einen Ausdruck einblendet, der die wichtigsten Informationen des gefundenen Datensatzes enthält:
- Artikelname & ", " & Liefereinheit etwa liefert Einträge der Tabelle tblArtikel wie Chai, 10 Kartons x 20 Beutel.
- KundenCode & " – " & Firma zeigt Daten aus tblKunden wie ALFKI – Alfreds Futterkiste an.
Beachten Sie, dass diese Ausdrücke gleichzeitig als Grundlage für die Suchabfrage dienen – bei der Suche in allen konfigurierten Tabellen werden also nur die so festgelegten Ausdrücke durchsucht!
Der Bereich oben rechts legt die Felder fest, die für die Anzeige des Suchergebnisses und für die Suche herangezogen werden. Die Unterscheidung erfolgt über die beiden Ja/Nein-Felder auf der rechten Seite.
Der letzte Bereich unten rechts ist ebenfalls wichtig: Dort können Sie die Formulare auswählen, welche beim Anwenden der Tastenkombination Strg + F zum Anzeigen des im aktuellen Datensatz des Konfigurationsformulars definierten Suchformulars führen. Betätigt der Benutzer Strg + F, wenn kein Formular geöffnet ist oder eines, für das keine Suche konfiguriert wurde, dann öffnet sich das Suchformular und bietet die globale Suche über alle festgelegten Tabellen an.
Globale Suche im Einsatz
Wie genau funktioniert nun die eigentliche globale Suche Diese bietet ein einziges Suchformular, das dynamisch den Gegebenheiten angepasst wird. Das Formular sieht wie in Bild 2 aus. Über das oberste Kombinationsfeld wählt der Benutzer aus, wonach er suchen möchte – entweder nach allen Daten, welche die Suche abdeckt, oder nach etwas Speziellem wie Artikel oder Kunden.
Bild 2: Die globale Suche in Aktion
Hat er sich für Letzteres entschieden, kann er mit dem zweiten Kombinationsfeld eines der Felder auswählen, die in der Konfiguration als Suchkriterien festgelegt wurden. Das Feld Suchbegriff schließlich nimmt den Suchbegriff auf und filtert die in der Ergebnisliste angezeigten Einträge nach jedem Tastenanschlag. Das oberste Kombinationsfeld zur Auswahl der zu durchsuchenden Objekte wird dabei automatisch vorbelegt, wenn der Benutzer Strg + F drückt, während eines der unter Aufrufende Formulare in der Konfiguration angegebenen Formulare den Fokus hat.
Einsatz der globalen Suche in eigenen Anwendungen
Wenn Sie diese Suche in einer eigenen Anwendung verwenden möchten, brauchen Sie nur ein paar Objekte zu importieren, das Suchformular optisch den übrigen Objekten Ihrer Datenbank anzupassen und die Suche wie oben beschrieben zu konfigurieren. Sie benötigen die folgenden Elemente:
- Tabellen tblGlobalSearchOptionsFields, tblGlobalSearchOptionsForms und tblGlobalSearchOptionsTables
- Formulare frmGlobalSearch und frmGlobalSearchOptions
- Makros AutoExec und AutoKeys
- Modul mdlGlobalSearch
Falls schon eines oder beide Makros vorhanden sind, fügen Sie die enthaltenen Befehle einfach hinzu. Für alle, die unsere globale Suche nicht nur einsetzen, sondern auch noch weiter anpassen oder um Funktionen erweitern möchten, beschreiben die folgenden Seiten detailliert den Aufbau der Lösung.
Tastenkombination
Beginnen wir doch gleich dort, wo auch der Benutzer Ihrer Anwendung wohl anfangen würde, wenn er kein Tastaturfeind ist und auch in anderen Anwendungen auf Strg + F als Allheilmittel für das Auffinden vermisster Informationen setzt: beim Füllen der Tastenkombination mit Leben.
Hier gibt es zwei Möglichkeiten: Entweder Sie legen eine solche Tastenkombination nur für bestimmte Elemente wie etwa Formulare fest, oder Sie definieren diese anwendungsweit. Im folgenden Fall wollen wir die zweite Variante wählen, da die Suche auch verfügbar sein soll, wenn gar kein Formular geöffnet ist.
Wie also öffnen wir das Suchformular durch pures Betätigen von Strg + F Dies geschieht ganz einfach mithilfe des für die Definition von globalen Tastenkombinationen vorgesehenen Makros namens Autokeys. Legen Sie also ein leeres Makro an und speichern Sie es unter diesem Namen.
Aktivieren Sie dann die Anzeige der Spalte Makroname und tragen Sie dort den Ausdruck ^f ein, was der Tastenkombination Strg + F entspricht. Als Aktion legen Sie AusführenCode mit dem Parameter =GlobalSearch() fest, was den Aufruf der gleichnamigen, öffentlich deklarierten Funktion auslöst (siehe Bild 3). Diese können Sie zunächst in dieser Form in ein Standardmodul eintragen und gleich testen, ob die Tastenkombination funktioniert:
Bild 3: Das AutoKeys-Makro führt auf Tastendruck die gewünschte Funktion aus.
Public Function GlobalSearch() On Error Resume Next DoCmd.OpenForm "frmGlobalSearch", _ OpenArgs:=Screen.ActiveForm.Name If Err.Number = 2475 Then DoCmd.OpenForm "frmGlobalSearch" End If End Function
Die Routine ruft gleich das Formular frmGlobalSearch auf und übergibt, wenn gerade ein anderes Formular den Fokus hat, dessen Namen als Öffnungsargument. Dieses wird in frmGlobalSearch ausgewertet – dazu später mehr.
Unter einer speziellen Konstellation kann es vorkommen, dass das AutoKeys-Makro partout seinen Dienst verweigert – wenn Access einen anderen Namen für das Makro festgelegt hat, das auf Tastenkombinationen reagieren soll. Das prüfen Sie ganz einfach mit folgender Anweisung, die Sie im Direktfenster des VBA-Editors (Strg + G) absetzen:
Debug.Print Application.GetOption("Key assignment macro")
Liefert dies ein anderes Resultat als AutoKeys, beispielsweise Tastaturbelegung, haben Sie zwei Möglichkeiten: Entweder Sie legen auch noch ein zweites Makro für diesen Fall an (andere Namen als AutoKeys oder Tastaturbelegung sind eigentlich unüblich – aber nicht auszuschließen), oder Sie prüfen den Namen des AutoKeys-Makros und stellen diesen gegebenenfalls auf AutoKeys ein. Dies müssten Sie wiederum in einer VBA-Routine erledigen, die beim Start der Anwendung durch das Makro AutoExec aufgerufen wird (siehe Bild 4):
Bild 4: Das AutoExec-Makro ruft eine Funktion auf, die den Namen des AutoKeys-Makros einstellt.
Public Function CheckAutokeys() If Not Application.GetOption("Key assignment macro") = "Autokeys" Then Application.SetOption "Key assignment macro", "Autokeys" End If End Function
Die Möglichkeit, dass ein Anwender andere Anwendungen einsetzt, deren AutoKeys-Makro anders als AutoKeys heißt, lassen wir hier außen vor – im wahren Leben sollten Sie aber den Ausgangszustand vor dem Schließen der Anwendung wieder herstellen.
Suche konfigurieren
Bevor der Benutzer die Suche einsetzen kann, müssen Sie einige Einstellungen vornehmen. Dies soll über entsprechende Formulare geschehen, wobei die Einstellungen in einer entsprechenden Tabelle gespeichert werden. Mögliche Einstellungen:
- Angabe eines Titels, beispielsweise Kunden oder Artikel
- Tabelle, aus der die Daten stammen
- Felder, die durchsucht und angezeigt werden sollen
- Formular, das geöffnet werden soll, wenn der Benutzer auf einen Eintrag des Suchergebnisses klickt
- Formulare, in deren Zusammenhang bestimmte Suchen aktiviert werden sollen
Zum Speichern dienen drei Tabellen namens tblGlobalSearchOptionsTables, tblGlobalSearchOptionsFields und tblGlobalSearchOptionsForms. tblGlobalSearchOptionsTables enthält diese Felder:
- ID: Primärschlüsselfeld
- Title: Titel, der im Suchfenster angezeigt wird
- TableOrQuery: Tabelle oder Abfrage, aus der die Suchfelder stammen
- PrimaryKey: Primärschlüssel dieser Tabelle, mit der auch das später anzuzeigende Formular gefiltert werden soll
- Formname: Name des zu öffnenden Formulars
- View, Filtername, WhereCondition, DataMode, WindowMode und OpenArgs: Parameter für das Öffnen des Formulars per DoCmd.OpenArgs
Die Tabelle tblGlobalSearchOptionsFields enthält diese Felder:
- ID: Primärschlüsselfeld
- TableID: Fremdschlüsselfeld zum Festlegen eines Datensatzes aus tblGlobalSearchOptionsTables
- Fieldname: Name des Feldes
- ShowField: Gibt an, ob das Feld im Suchergebnis angezeigt werden soll.
- SearchField: Gibt an, ob das Feld in die Suche einbezogen werden soll.
- ColumnWidth: Breite der Spalte dieses Feldes im Listenfeld
- OrderID: Repräsentiert die Reihenfolge-Position des Feldes.
Die Tabelle tblGlobalSearchOptionsForms ordnet den verschiedenen Suchen die Namen der Formulare zu, in deren Kontext eine Suche aufgerufen wird. Bild 5 zeigt die drei Tabellen im Beziehungen-Fenster.
Bild 5: Tabellen der globalen Suche im Beziehungen-Fenster
Konfigurationsformular
Die Konfiguration soll über ein Formular namens frmGlobalSearchOptions erfolgen, das jeweils einen Datensatz der Tabelle tblGlobalSearchOptionsTables anzeigt und die damit verknüpften Datensätze der Tabelle tblGlobalSearchOptionFields in einem Unterformular darstellt (sfmGlobalSearchOptions).
Beginnen Sie mit dem Unterformular: Dazu legen Sie ein neues leeres Unterformular an und stellen die Datenherkunft auf die Tabelle tblGlobalSearchOptionsFields ein.
Ziehen Sie alle Felder, die das Unterformular anzeigen soll, in den Detailbereich der Entwurfsansicht (siehe Bild 6). Wir wollen dort nur die Felder auswählen, deren Reihenfolge festlegen und einstellen, welche Felder angezeigt und/oder für die Suche verwendet werden.
Bild 6: Entwurf des Unterformulars sfmGlobalSearchOptions
Später peppen wir das Formular noch auf, bis hierher reicht uns diese Fassung jedoch. Kommen wir zum Hauptformular, das auf der Tabelle tblGlobalSearchOptionsTables als Datenherkunft basiert.
Hier ziehen Sie einfach alle Felder außer dem Primärschlüsselfeld in den Detailbereich. Außerdem fügen Sie per Drag and Drop das Unterformular sfmGlobalSearchOptions zum Entwurf des Hauptformulars hinzu.
In der Datenblattansicht sieht das Unterformular dann etwa wie in Bild 7 aus.
Bild 7: Das Konfigurationsformular im Rohbau
Konfigurationsformular optimieren
Mit dem Formular frmGlobalSearchOptions lassen sich zwar nun schon die benötigten Daten eintragen, aber jeder Wert muss von Hand eingetippt werden – hier gibt es also Optimierungspotenzial. Beginnen wir mit dem Feld zur Eingabe der Tabelle oder Abfrage: Diese sollen Sie natürlich nicht eintippen, sondern aus einer Liste auswählen.
Sie wandeln das Textfeld also in ein Kombinationsfeld um (Kontextmenü ändern zu|Kombinationsfeld) und stellen die Datensatzherkunft auf den folgenden Ausdruck ein:
SELECT Name FROM MSysObjects WHERE Name Not Like "MSys*" AND (Type = 1 OR Type = 5) ORDER BY MSysObjects.Name;
Das Kombinationsfeld erlaubt nun bereits das komfortable Auswählen der gewünschten Tabelle oder Abfrage (siehe Bild 8). Nach der Auswahl einer Tabelle oder Abfrage soll das Feld PrimaryKey, ebenfalls als Kombinationsfeld ausgeführt, mit den Feldnamen der auswählten Tabelle gefüllt werden. Dazu legen Sie für das Steuerelement cboTableOrQuery eine neue Ereignisprozedur an, indem Sie für die Eigenschaft Nach Aktualisierung des Steuerelements den Wert [Ereignisprozedur] auswählen und dann auf die Schaltfläche mit den drei Punkten (…) rechts neben dem Eigenschaftsfeld klicken. Im nun erscheinenden VBA-Editor finden Sie bereits den Prozedurrumpf vor, den Sie wie folgt ergänzen:
Bild 8: Einfache Tabellenauswahl
Private Sub cboTableOrQuery_AfterUpdate() If Not IsNull(Me!cboTableOrQuery) Then Me!cboPrimaryKey.RowSourceType = "Field List" Me!cboPrimaryKey.RowSource = Me!cboTableOrQuery End If End Sub
Dies stellt die Eigenschaft Herkunftsart auf den Wert Feldliste und die Eigenschaft Datensatzherkunft auf den Namen der Tabelle ein, welche die Feldliste liefern soll – in diesem Fall die Tabelle, die der Benutzer im Kombinationsfeld cboTableOrQuery ausgewählt hat. Nach Auswahl der Tabelle oder Abfrage bietet das Kombinationsfeld cboPrimaryKey nun alle dort enthaltenen Felder an (siehe Bild 9).
Bild 9: Auswahl des Primärschlüsselfelds einer Tabelle oder Abfrage
Warum aber soll der Benutzer den Primärschlüssel überhaupt auswählen, wenn dieser ja meistens schon definiert ist Er sollte zumindest die Möglichkeit erhalten, dies zu tun. Das für PrimaryKey angegebene Feld soll beim Öffnen des Detailformulars eines aus der Ergebnisliste ausgewählten Datensatzes als WhereCondition zum Einsatz kommen. Es kann aber natürlich auch vorkommen, dass hier nicht das Primärschlüsselfeld, sondern ein anderes benötigt wird.
Einigen wir uns auf einen Kompromiss: Das Feld cboPrimaryKey soll zwar alle Felder der Tabelle oder Abfrage zur Auswahl anbieten, aber der Primärschlüssel der Tabelle soll automatisch ermittelt und voreingestellt werden. Das spart dann in den meisten Fällen einen Maus-Klick ein.
Für das Ermitteln des Primärschlüssels verwenden wir die im Beitrag Tipps und Tricks aus Ausgabe 3/2009 (Shortlink 671) vorgestellte Funktion GetPrimaryKeyFields und passen die durch das Ereignis Nach Aktualisierung ausgelöste Prozedur wie in Listing 1 an.
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