Datensätze nach Zahl ausgeben

Sie kennen das sicher vom Drucken-Dialog, wo Sie einzelne Zahlen oder Zahlenbereiche angeben können, um die betroffenen Seiten zu drucken – also beispielsweise 1-2, 3-5 und so weiter. Eine solche Möglichkeit wollen wir auch für das Filtern von Datensätzen in der Datenblattansicht schaffen. Der Benutzer soll also eine oder mehrere Seitenzahlen oder Bereiche von Seiten in ein Textfeld eingeben können, nach denen dann gefiltert wird.

Vorbereitung

Wir benötigen ein Hauptformular, welches das Textfeld für die Eingabe der gewünschten Filterausdrücke enthält sowie ein Unterformular, das die gefilterten Datensätze anzeigt. Das Unterformular soll die Tabelle tblArtikel als Datensatzquelle verwenden, und zwar als Abfrage formuliert, welche die Artikel aufsteigend nach dem Wert des Feldes ArtikelID sortiert. Das Unterformular namens sfmArtikelNachBereich enthält alle Felder der zugrundeliegenden Abfrage. Außerdem stellen wir seine Eigenschaft Standardansicht auf Datenblatt ein.

Das Formular sfmArtikelNachBereich fügen wir dann dem Hauptformular als Unterformular hinzu. Außerdem legen wir im Hauptformular ein Textfeld namens txtBereiche an. Neben diesem Textfeld legen wir zwei Schaltflächen an – eine zum Anwenden des Filters und eine zum Zurücksetzen. Für das Hauptformular stellen wir außerdem die Eigenschaften Datensatzmarkierer, Navigationsschaltflächen und Bildlaufleisten auf Nein und Automatisch zentrieren auf Ja ein.

Die beiden Eigenschaften Horizontaler Anker und Vertikaler Anker des Unterformular-Steuerelements erhalten den Wert Beide, das Bezeichnungsfeld des Unterformular-Steuerelements löschen wir. Das Hauptformular sieht dann inklusive Steuerelementen und Unterformular wie in Bild 1 aus.

Entwurf des Formulars zum Filtern nach Zahlenbereichen

Bild 1: Entwurf des Formulars zum Filtern nach Zahlenbereichen

Anforderungen

Welche Filtermöglichkeiten wollen wir schaffen Hier sind die einzelnen Möglichkeiten:

  • Durch Komma getrennte Zahlen, also zum Beispiel 1, 3, 5, sollen die erste, dritte und fünfte Seite liefern.
  • Zwei durch einen Bindestrich verbundene Zahlen geben einen Bereich an, zum Beispiel soll 1-4 alle Datensätze von 1 bis 4 liefern.
  • Ein Bindestrich vor einer Zahl soll alle Datensätze bis zu dieser Zahl liefern. -5 soll also alle Datensätze von 1 bis 5 ausgeben.
  • Ein Bindestrich nach einer Zahl soll alle Datensätze ab dieser Zahl liefern (einschließlich dieser Zahl). 3- soll also alle Datensätze ab 3 ausgeben.

Diese Möglichkeiten sollen auch noch kombiniert werden können, und zwar jeweils getrennt durch das Komma-Zeichen.

Und was auch noch nicht geklärt ist: Worauf genau sollen sich die Zahlen beziehen Dazu gibt es zwei Möglichkeiten:

  • Den Index der angezeigten Datensätze.
  • Den Primärschlüsselwert der angezeigten Datensätze.

Da wir vorher nie wissen, wie die Wünsche des Benutzers aussehen, fügen wir dazu noch eine Optionsgruppe mit den beiden Möglichkeiten hinzu.

So kann der Benutzer auch nach der Sortierung etwa nach dem Artikelnamen die Datensätze nach dem Index filtern lassen. Dazu fügen wir noch die Optionsgruppe ogrFilter wie in Bild 2 zum Hauptformular hinzu.

Optionsgruppe zum Einstellen des Kriteriums zum Filtern

Bild 2: Optionsgruppe zum Einstellen des Kriteriums zum Filtern

Einzelne Filterausdrücke extrahieren

Wir beginnen einfach und wollen zunächst alle Filterausdrücke aus dem Textfeld txtBereiche extrahieren. Das sind also alle Teile der im Textfeld enthaltenen Zeichenkette, die durch ein Komma voneinander getrennt werden.

Um diese schnell zu erhalten, nutzen wir die Split-Funktion, um aus der Zeichenkette ein String-Array mit den einzelnen Elementen zu bilden.

Dieses durchlaufen wir dann in einer For…Next-Schleife über alle Elemente. Die Indexwerte dieser Elemente ermitteln wir dabei mit den Funktionen LBound (unterer Indexwert) und UBound (oberer Indexwert):

Private Sub cmdFiltern_Click()
     Dim strFilter As String
     Dim strBereiche As String
     Dim strVergleichswerte() As String
     Dim i As Integer
     strBereiche = Nz(Me!txtBereiche, "")
     strVergleichswerte = Split(strBereiche, ",")
     For i = LBound(strVergleichswerte) To  UBound(strVergleichswerte)
         Debug.Print strVergleichswerte(i)
     Next i
End Sub

Wenn der Benutzer nun 1,3,5 eingibt, erhalten wir diese Ausgabe:

1
3
5

Damit lässt sich schon einmal arbeiten. Wenn wir Bereiche eingeben, erhalten wir auch die gewünschten Informationen, zum Beispiel bei -2, 4, 7-9, 75-. Das liefert:

-2
4
7-9
75-

Unzulässige Zeichen erkennen

Bevor wir überhaupt in die Analyse der einzelnen, durch Kommata getrennten Elemente einsteigen, wollen wir direkt prüfen, ob der Ausdruck unzulässige Zeichen enthält. Dazu nutzen wir die folgende Funktion, der wir zwei Parameter übergeben:

  • die zu untersuchende Zeichenfolge und
  • eine Zeichenkette mit den zulässigen Zeichen.

Der Aufruf dieser Funktion sieht beispielsweise wie folgt aus:

  NurZulaessigeZeichen("x-2, 4, 7-9, 75-", "[0-9,-]")

Als Ergebnis soll eine Zeichenkette ohne nicht zulässige Zeichen zurückgeliefert werden.

In diesem Fall ist das führende x ein nicht zulässiges Zeichen, also sollte der Aufruf dieses Ergebnis liefern:

-2, 4, 7-9, 75-

Die Funktion sieht wie folgt aus:

Public Function NurZulaessigeZeichen(strText As String,  strZeichen As String)
     Dim i As Integer
     Dim strTemp As String
     For i = 1 To Len(strText)
         If Mid(strText, i, 1) Like strZeichen Then
             strTemp = strTemp & Mid(strText, i, 1)
         End If
     Next i
     NurZulaessigeZeichen = strTemp
End Function

Die Funktion erwartet die nicht zulässigen Zeichen in einer Form, wie Sie mit einem Like-Vergleich genutzt werden kann, also in eckigen Klammern. Außerdem können Bereiche von Zeichen wie etwa die Zahlen von 0 bis 9 vereinfacht durch 0-9 angegeben werden.

Die Funktion durchläuft alle Zeichen der zu untersuchenden Zeichenkette in einer For…Next-Schleife, wobei jeweils ein Zeichen mit dem Like-Operator mit den Vergleichszeichen vergleichen wird. Ist das Zeichen in den mit dem zweiten Parameter übergebenen Zeichen enthalten, wird dieses an die Zeichenkette der Variablen strTemp angehängt. Diese wird nach dem Durchlaufen aller Zeichen an die aufrufende Instanz zurückgegeben.

Der Sinn dieser Funktion ist in unserem Fall, unerwünschte und gegebenenfalls versehentlich eingegebene Zeichen zu extrahieren. Diese Funktion bauen wir daher direkt in die Ereignisprozedur cmdFiltern_Click ein:

Private Sub cmdFiltern_Click()
     ...
     strBereiche = Nz(Me!txtBereiche, "")
     strBereiche = NurZulaessigeZeichen(strBereiche,  "[,-0-9]")
     ...
End Sub

Bereiche analysieren

Diese Bereiche analysieren wir nun. Dabei gibt es die folgenden Fälle:

  • eine Zahl, zum Beispiel 4,
  • eine Zahl mit folgendem Bindestrich, zum Beispiel 75-,
  • eine Zahl mir führendem Bindestrich, zum Beispiel -2 und
  • zwei durch einen Bindestrich getrennte Zahlen, zum Beispiel 7-9.

Diese vier Fälle müssen wir zunächst erkennen. Dazu verwenden wir eine neue Funktion, die wir in der For…Next-Schleife für jedes durch Komma getrennte Element einmal aufrufen:

For i = LBound(strVergleichswerte) To  UBound(strVergleichswerte)
     Debug.Print strVergleichswerte(i)
     FilterkriteriumErmitteln strVergleichswerte(i)
Next i

Die Funktion sieht zunächst wie folgt aus:

Private Function FilterkriteriumErmitteln(ByVal  strVergleichswert As String)
     Dim intPos As Integer
     strVergleichswert = Replace(strVergleichswert, " ", "")
     intPos = InStr(1, strVergleichswert, "-")
     Select Case intPos
         Case 0
             Debug.Print "kein Minus"
         Case 1
             Debug.Print "Minus an erster Stelle"
         Case Else
             If intPos = Len(strVergleichswert) Then
                 Debug.Print "Minus an letzter Stelle"
             Else
                 Debug.Print "Minus dazwischen"
             End If
     End Select
End Function

Die Funktion ersetzt zunächst alle Leerzeichen durch leere Zeichenketten. Dann ermittelt sie in der Variablen intPos die Position des Minuszeichens (). Im Falle von 0 ist kein Minuszeichen vorhanden, was wir aktuell einfach im Direktbereich vermerken. Lautet der Wert von intPos hingegen 1, befindet sich das Minuszeichen an der ersten Stelle, was auf einen Ausdruck wie -3 hindeutet. In allen anderen Fällen ist eine weitere Untersuchung nötig, die wir im Else-Zweig der Select Case-Bedingung prüfen. Hier prüfen wir, ob intPos gleich der Anzahl der Zeichen der übergebenen Zeichenkette entspricht, was bedeuten würde, dass sich das Minus-Zeichen an der letzten Stelle befindet. In allen anderen Fällen befindet sich das Minuszeichen nicht an erster und nicht an letzter Stelle, der Ausdruck sollte also wie 1-3 lauten.

Vergleichsausdrücke ermitteln

Nun reichern wir die obige Prozedur um die resultierenden Vergleichsausdrücke an. Dabei betrachten wir zunächst nur den Fall, dass wir das ID-Feld als Vergleichsfeld nutzen wollen und nicht den Index der angezeigten Elemente – der ist nämlich noch etwas komplizierter zu handhaben.

Die neue Version der Prozedur finden Sie in Listing 1. Die Prozedur erwartet nun mit dem ersten Parameter auch noch den Namen des Feldes, das als Vergleichsfeld verwendet werden soll. Im Vergleichswert entfernen wir die Leerzeichen und ermitteln dann die Position eines gegebenenfalls enthaltenen Minuszeichens.

Public Function FilterkriteriumErmitteln(strVergleichsfeld As String, ByVal strVergleichswert As String)
     Dim intPos As String
     Dim strVergleichsausdruck As String
     strVergleichswert = Replace(strVergleichswert, " ", "")
     intPos = InStr(1, strVergleichswert, "-")
     Select Case intPos
         Case 0
             strVergleichsausdruck = strVergleichsfeld & " = " & strVergleichswert
         Case 1
             strVergleichsausdruck = strVergleichsfeld & " <= " & Mid(strVergleichswert, intPos + 1)
         Case Else
             If intPos = Len(strVergleichswert) Then
                 strVergleichsausdruck = strVergleichsfeld & " >= " & Mid(strVergleichswert, 1, intPos - 1)
             Else
                 strVergleichsausdruck = "(" & strVergleichsfeld & " >= " & Mid(strVergleichswert, 1, intPos - 1) _
                     & " AND " & strVergleichsfeld & " <= " & Mid(strVergleichswert, intPos + 1) & ")"
             End If
     End Select
     FilterkriteriumErmitteln = strVergleichsausdruck
End Function

Listing 1: Ermittlung der Vergleichsausdrücke

Im ersten Case-Zweig der Select Case-Bedingung tragen wir für die Variable strVergleichsausdruck den Namen des Vergleichsfeldes, ein Gleichheitszeichen und den Vergleichswert ein, und zwar in der Form = .

Der Case-Zweig, der davon ausgeht, dass das Minuszeichen gleich das erste Zeichen ist, fügt den Namen des Vergleichsfelds mit dem Vergleichsoperator <= und dem Teil aus strVergleichswert zusammen, der nach dem Minuszeichen folgt, also in der Form <= .

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

Schreibe einen Kommentar