Filtern und sortieren per Kontextmenü

Lies diesen Artikel und viele weitere mit einem kostenlosen, einwöchigen Testzugang.

Eigentlich bieten die Datenblatt- und auch die Formularansicht eine Menge Werkzeuge, mit denen der Benutzer die Daten nach Wunsch filtern oder sortieren kann. Dummerweise stehen diese Möglichkeiten in der Runtime-Version von Access nicht zur Verfügung. Damit Sie auch Benutzer ohne Vollversion mit dem gewohnten Komfort beglücken können, bringen wir Ihren Formularen neue Techniken zum Aufruf von Filtern und Sortierungen bei.

Access bietet vor allem seit Access 2007 sehr praktische Filter- und Sortierfunktionen. So können Sie beispielsweise in der Datenblattansicht auf den kleinen Pfeil im Spaltenkopf klicken, um die Sortier- und Filteroptionen auszuwählen. Das daraufhin erscheinende Popup-Menü zeigt zwei Einträge zum Sortieren der Feldwerte in aufsteigender und absteigender Reihenfolge, die Möglichkeit zur Eingabe eines Textfilters oder auch das Auswählen konkreter Werte, die angezeigt werden sollen – oder auch nicht (s. Bild 1).

pic001.png

Bild 1: Filter- und Sortiermöglichkeiten in der Datenblattansicht

Hinweis: Access 2003 und älter bieten nicht so praktische Filter- und Sortiermöglichkeiten, daher gehen wir auf diese hier nicht ein. Unsere Lösung können Sie hingegen auch mit älteren Access-Versionen verwenden – wir werfen nur einen genauen Blick auf die Access 2007/2010-Techniken, um die Anforderungen für die Lösung zu ermitteln.

Sie können Filter und Sortierungen für mehrere Spalten festlegen, wobei diese mit UND verknüpft werden. Damit lassen sich etwa alle Adressen auswählen, deren Vorname mit A und deren Nachname mit B beginnt. Wenn Sie das Popupfenster zum Einstellen von Filter- und Sortierkriterien für eine gefilterte Spalte anzeigen, ist der Eintrag Filter löschen aus <Feldname> aktiviert (s. Bild 2). Hiermit können Sie einzelne Filter wieder entfernen.

pic003.png

Bild 2: Löschen einzelner Filter

Alle Filter entfernen Sie mit einem Eintrag im Ribbon, der unter Access 2010 wie in Bild 3 aussieht.

pic004.png

Bild 3: Entfernen aller aktiven Filter

Die Filter- und Sortiermöglichkeiten stehen auch in der Formularansicht über das Kontextmenü zur Verfügung (s. Bild 4).

pic002.png

Bild 4: Filtern per Kontextmenü in der Formularansicht

Datentypabhängiger Filter

Die Möglichkeiten der Filterfunktion erschließen sich erst, wenn Sie sich einmal die Einträge des Kontextmenüs für verschiedene Datentypen ansehen. Wenn Sie beispielsweise das Kontextmenü für ein Datumsfeld öffnen, können Sie sogar alle Daten eines bestimmten Quartals oder Monats auswählen (s. Bild 5).

pic005.png

Bild 5: Umfangreiche Filtermöglichkeiten für Datumsangaben

All diese Möglichkeiten wollen wir beim Nachbau einer solchen Filter- und Sortierfunktion via Kontextmenü natürlich offenhalten.

Spezialfall Runtime

Neben den älteren Access-Versionen, die weniger gut mit Filter- und Sortierfunktionen ausgestattet sind, gibt es mit der Runtime-Version von Access einen weiteren Spezialfall: Die praktischen Helferlein lassen sich dort nur über die Spaltenköpfe in der Datenblattansicht aufrufen, aber nicht über Kontextmenüs.

Der Grund für das Fehlen der Filter- und Sortierfunktionen in Anwendungen, die mit der Access-Runtime geöffnet werden, ist ganz einfach: Microsoft hat dort ganz einfach alle eingebauten Menüs beziehungsweise Ribbons sowie Kontextmenüs rausgeworfen.

Sie können das Verhalten der Runtime für eine beliebige Datenbankanwendung folgendermaßen nachstellen:

  • Access 2003 und älter: Öffnen Sie die Datenbank mit einer Verknüpfung wie c:\Programme\Microsoft Office\Office<Version>\MSAccess.exe <Pfad zur Datenbank> /runtime.
  • Access 2007 und jünger: ändern Sie einfach die Dateiendung auf .accdr und öffnen Sie die Datenbank.

Filter nachrüsten

Da Sie wahrscheinlich nicht alle Daten ausschließlich in Formularen in der Datenblattansicht anzeigen möchten, müssen Sie Anwendungen, die als Runtime-Version weitergegeben werden sollen, mit eigenen Filterfunktionen ausrüsten – zumindest dort, wo keine Datenblattansicht vorliegt.

Wir beginnen mit zwei Einträgen in das Kontextmenü, die das auf- und absteigende Sortieren des jeweiligen Feldes erlauben. Bevor wir damit beginnen, sind jedoch einige Überlegungen notwendig:

  • Sollen ein oder mehrere Felder sortiert werden können
  • Falls wir mehrere Felder sortieren, in welcher Reihenfolge wird sortiert Verwenden wir die Aktivierreihenfolge, oder soll die Reihenfolge beliebig einstellbar sein
  • Wie wird das Sortierkriterium nach der Zusammenstellung angewendet

Die Sortierung nach nur einem Feld wäre am einfachsten und dürfte in der Praxis auch für die meinsten Fälle ausreichend sein. Jedoch kann es durchaus auch vorkommen, dass der Benutzer nach mehr als einem Kriterium sortieren möchte.

In dem Fall müssen wir uns überlegen, in welcher Reihenfolge der Felder die Sortierungg erfolgen. Bei der eingebauten Sortierfunktion wird das jeweils neueste Sortierkriterium vorne an den OrderBy-Ausdruck angehängt. Wenn Sie also zunächst eine aufsteigende Sortierung nach dem Vornamen anwenden, hat die OrderBy-Eigenschaft des Formulars den folgenden Wert:

[tblAdressen].[Vorname]

Wenn Sie anschließend eine absteigende Sortierung nach dem Nachnamen festlegen, sieht der Ausdruck so aus:

[tblAdressen].[Nachname] DESC, [tblAdressen].[Vorname]

Die Reihenfolge ist insofern wichtig, als dass immer zuerste nach dem erstgenannten Feld sortiert wird und erst dann nach den folgenden Feldern. Das heißt, dass sich die hinteren Sortierkriterien nur noch auswirken, wenn die vorderen Felder gleiche Inhalte aufweisen, die in der Sortierreihenfolge gleichrangig sind.

Übernehmen wir also dieser Vorgehensweise und stellen das Sortierkriterium so zusammen, dass die zuletzt hinzugefügte Sortierung die höchste Priorität erhält.

Wer genau beobachtet, stellt übrigens fest, dass die Standardfunktion zum Hinzufügen von Sortierkriterien nicht das Entfernen einzelner Sortierkriterien erlaubt – dies funktioniert nur für die komplette Sortierung. Dieses Feature werden wir natürlich noch hinzufügen.

Unser Kontextmenü sollte also die folgenden Einträge enthalten:

  • Aufsteigende Sortierung hinzufügen
  • Absteigende Sortierung hinzufügen
  • Sortierung für dieses Feld entfernen
  • Sortierung für alle Felder entfernen (da diese Funktion in der Runtime gar nicht greifbar ist)

Hinzufügen der Kontextmenüeinträge

Als Nächstes kümmern wir uns um die Erstellung der Kontextmenüeinträge. Diese können wir entweder dauerhaft speichern oder zur Laufzeit zusammenstellen. Da Sie wie der Autor dieser Zeilen nach der Lektüre zahlloser Beiträge zu diesem Thema in der dynamischen Erstellung von Kontextmenüs bewandert sein dürften, wählen wie diese Variante.

Die Funktionen zum Sortieren der Datensätze ist die einfachere, sie dürfte vor allem in Datenblatt- und Endlosansichten Verwendung finden. Die hier vorgestellte Lösung kann in Haupt- und Unterformularen und auch in modalen Dialogen eingesetzt werden.

Erstellen der Kontextmenüs

Unser erstes Ziel ist das Erstellen eines Kontextmenüs wie in Bild 6. Der kleine Haken ist, dass wir je nach Datentyp des Feldes unterschiedliche Texte anzeigen wollen. Damit möchten wir auch Benutzer einfangen, die sonst wenig bis gar nicht mit Datenbankanwendungen arbeiten.

pic006.png

Bild 6: Kontextmenü zum Sortieren eines Textfeldes

Für ein Textfeld lautet der Text zum Anwenden einer aufsteigenden Sortierung beispielsweise Von A bis Z sortieren und umgekehrt Von Z bis A sortieren, bei Datumsfeldern soll es Von früheren zu späteren Daten sortieren und Von späteren zu früheren Daten sortieren und so weiter.

Ablauf der Erstellung

Die Erstellung eines Kontextemenüs beginnt mit dem Laden des Formulars, dessen Steuerelemente mit den Sortier-Funktionen gefüllt werden sollen. Die komplette Funktionalität dafür steckt in zwei Klassenmodulen namens clsSortAndFilter und clsSortAndFilterControl.

Für den Einbau der Sortierfunktion brauchen Sie nur wenige Zeilen zum betroffenen Formular hinzuzufügen. Die erste deklariert ein Objekt auf Basis der Klasse clsSortAndFilter und landet im Kopf des Formularmoduls:

Dim objSortAndFilter As clsSortAndFilter

Danach legen Sie eine Ereignisprozedur an, die durch das Ereignis Beim Laden des Formulars ausgelöst wird. Beachten Sie, dass Sie bei Verwendung eines Unterformulars auch dort die Beim Laden-Ereignisprozedur anlegen müssen.

Diese Prozedur erstellt lediglich eine neue Instanz der Klasse clsSortAndFilter und weist sie der frisch deklarierten Objektvariablen zu. Außerdem verwendet es die Eigenschaft Form dieser Klasse, um einen Verweis auf das mit Sortiermenüs zu bestückende Formular zu übergeben:

Private Sub Form_Load()
    Set objSortAndFilter = New clsSortAndFilter
    With objSortAndFilter
    Set .Form = Me
    End With
End Sub

Steuerelemente mit Kontextmenüs versehen

Das Zuweisen des Formularverweises an die Eigenschaft Form löst die Property Get-Methode aus Listing 1 aus.

Listing 1: Diese Property Set-Methode ist die Steuerzentrale für das Anlegen der Sortier-Kontextmenüs.

Public Property Set Form(frm As Form)
    Dim ctl As Control
    Dim strControlSource As String
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Dim fld As DAO.Field
    Set m_Form = frm
    Set colOrderBy = New Collection
    Set colCommandbarButtons = New Collection
    Set db = CurrentDb
    Set rst = db.OpenRecordset(m_Form.RecordSource, dbOpenDynaset)
    For Each ctl In m_Form.Controls
         strControlSource = ""
        On Error Resume Next
        strControlSource = ctl.ControlSource
        On Error GoTo 0
        If Len(strControlSource) > 0 Then
            ''Datentyp des Feldes herausfinden
            Set fld = rst.Fields(strControlSource)
            Select Case fld.Type
                ''Zahlentypen
                Case dbBigInt, dbByte, dbCurrency, dbDecimal, dbDouble, dbFloat, dbInteger, _
                        dbLong, dbNumeric, dbSingle
                    CreateSortBar "Aufsteigend sortieren", "Absteigend sortieren", "cbrNumber"
                    ctl.ShortcutMenuBar = "cbrNumber"
                ''Text
                Case dbChar, dbText, dbMemo, dbGUID
                    CreateSortBar "Von A bis Z sortieren", "Von Z bis A sortieren", "cbrText"
                    ctl.ShortcutMenuBar = "cbrText"
                ''Datum
                Case dbDate, dbTime, dbTimeStamp
                    CreateSortBar "Von früheren zu späteren Daten sortieren", _
                    "Von späteren zu früheren Daten sortieren", "cbrDate"
                    ctl.ShortcutMenuBar = "cbrDate"
                ''Boolean
                Case dbBoolean
                    CreateSortBar "Von Ja nach Nein sortieren", "Von Nein nach Ja sortieren", "cbrBoolean"
                    ctl.ShortcutMenuBar = "cbrBoolean"
                Case Else
                    Debug.Print fld.Name, fld.Type
            End Select
        End If
    Next ctl
End Property

Diese schreibt zunächst den Objektverweis in die private Variable m_Form, die im Kopf des Klassenmoduls wie folgt deklariert wird:

Private m_Form As Form

Dann erzeugt sie neue Instanzen der folgenden Collection-Objekte, deren Funktion wir gleich im Anschluss erläutern:

Public colOrderBy As Collection
Public colCommandbarButtons As Collection

Um später den Datentyp des Feldes zu untersuchen, an welches das aktuell untersuchte Steuerelement gebunden ist, erstellt die Prozedur ein neues Recordset-Objekt und füllt es mit den gleichen Daten, die auch das Formular enthält.

Danach durchläuft die Prozedur im Wesentlichen in einer For Each-Schleife alle Steuerelemente des Formulars auf m_Form. Das aktuelle Steuerelement wird dabei jeweils in der Variablen ctl gespeichert und genauer untersucht. Diese Untersuchung konzentriert sich darauf, ob das Steuerelement gebunden oder ungebunden ist. Dies findet die Prozedur über die Eigenschaft ControlSource heraus, die nur bei gebundenen Steuerelementen mit dem Namen des Herkunftsfeldes gefüllt ist.

Da diese Eigenschaft nur bei bestimmten Steuerelementtypen vorhanden ist und die Abfrage der Eigenschaft einen Fehler auslöst, wenn sie nicht vorhanden ist, wird die Fehlerbehandlung für diese Abfrage außer Kraft gesetzt. Die Prozedur leert also die Variable strControlSource und versucht sie dann mit dem Namen der Eigenschaft ControlSource (im Eigenschaftsfenster Steuerelementinhalt) zu füllen. Wenn die Variable nach diesem Versuch noch leer ist, ist das Steuerelement offensichtlich ungebunden und wird nicht mit einem Kontextmenü versehen. Anderenfalls wird das Steuerelement innerhalb einer If…Then-Bedingung genauer untersucht.

Dort kommt das vor Beginn der For Each-Schleife erzeugte und gefüllte Recordset-Objekt rst zum Zuge: Die Prozedur ermittelt dort das Feld, an welches das aktuelle Steuerelement gebunden ist, und speichert einen Verweis darauf in der Objektvariablen fld. Die folgende Select Case-Bedingung prüft daraufhin über die Eigenschaft Type den den Datentyp des Feldes und setzt die Prozedur in einem von vier Zweigen fort: für Zahlen, Texte, Datumsangaben und Ja/Nein-Felder.

Innerhalb dieser Zweige erfolgt zuerst der Aufruf der Prozedur CreateSortBar mit zwei Parametern. Diese enthalten die Texte, welche das Kontextemenü zum Aufwärts- und Abwärtssortieren des jeweiligen Feldes anzeigen soll.

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

Testzugang

eine Woche kostenlosen Zugriff auf diesen und mehr als 1.000 weitere Artikel

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar