{"id":55001072,"date":"2017-02-01T00:00:00","date_gmt":"2020-05-14T13:41:07","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1072"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Schneller_Filter","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/","title":{"rendered":"Schneller Filter"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg09.met.vgwort.de\/na\/4fbbc500170f4967a2d4d8f4b2734958\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Formulare in der Datenblattansicht bieten alle Filter- und Sortierm&ouml;glichkeiten, die das Benutzerherz begehrt. Allerdings sind diese nicht unbedingt immer schnell erreichbar &#8211; hier und da k&ouml;nnte es noch ein wenig fixer gehen. Ein Beispiel ist ein Filter, der nur die Datens&auml;tze anzeigt, die den Wert des aktuell markierten Feldes im jeweiligen Feld enthalten. Wenn Sie also etwa eine Reihe von Artikeln anzeigen, die einer bestimmten Kategorie angeh&ouml;ren und schnell nur noch die Artikel dieser Kategorie sehen wollen, ben&ouml;tigen Sie dazu mehrere Mausklicks. Dieser Beitrag zeigt, wie Sie verschiedene Suchen mit einem einfachen Klick auf eine Schaltfl&auml;che erledigen.<\/b><\/p>\n<p>Die Datenblattansicht von Access-Formularen bietet eine Reihe von M&ouml;glichkeiten, schnell nach Daten zu suchen oder diese zu sortieren.<\/p>\n<p>Dazu klicken Sie einfach auf das nach unten zeigende Dreieck rechts im Spaltenkopf der jeweiligen Spalte. Hier sehen Sie auf Anhieb zwei Eintr&auml;ge zum Sortieren in verschiedenen Richtungen oder zum Selektieren verschiedener, im aktuellen Feld enthaltener Werte (s. Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_01\/pic_1072_001.png\" alt=\"Filtern nach allen vorhandenen Werten\" width=\"499,6607\" height=\"306,9468\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Filtern nach allen vorhandenen Werten<\/span><\/b><\/p>\n<p>Der Untereintrag <b>Textfilter <\/b>liefert etwa f&uuml;r Textfelder weitere M&ouml;glichkeiten: Hier k&ouml;nnen Sie beispielsweise nach Datens&auml;tzen suchen, deren markiertes Feld einen benutzerdefinierten Wert enth&auml;lt. Bei Textfeldern k&ouml;nnen hier etwa die Vergleichsoperatoren <b>Gleich<\/b>, <b>Nicht gleich<\/b>, <b>Beginnt mit<\/b>, <b>Beginnt nicht mit<\/b>, <b>Enth&auml;lt <\/b>und weitere verwendet werden (s. Bild 2). Andere Felddatentypen halten dem Datentyp entsprechende Vergleichskriterien bereit.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_01\/pic_1072_002.png\" alt=\"Filtern nach benutzerdefinierten Vergleichswerten\" width=\"649,559\" height=\"308,8935\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Filtern nach benutzerdefinierten Vergleichswerten<\/span><\/b><\/p>\n<h2>Datens&auml;tze mit gleichem Feldwert finden<\/h2>\n<p>Was aber hier fehlt, ist die einfache M&ouml;glichkeit, schnell alle Eintr&auml;ge anzuzeigen, die den gleichen Wert im zurzeit markierten Feld aufweisen wie der aktuelle Datensatz. Und genau diese Funktion wollen wir nun nachr&uuml;sten. F&uuml;r das Feld Artikelname macht dies nat&uuml;rlich recht wenig Sinn, aber beim Lieferanten oder bei der Kategorie finden sich schnell Einsatzm&ouml;glichkeiten.<\/p>\n<p>Warum nicht beim Artikelnamen Nun: Dabei handelt es sich um ein Feld mit einem eindeutigen Index. Da nur jeweils ein Datensatz mit dem aktuellen Wert vorhanden ist, macht es wenig Sinn, danach zu filtern &#8230; au&szlig;er nat&uuml;rlich, wenn Sie etwa aus Gr&uuml;nden der &uuml;bersicht nur diesen einen Datensatz anzeigen m&ouml;chten. Also nehmen wir diese einfache Variante einfach mit hinzu. <\/p>\n<p>Sp&auml;ter wollen wir jedoch gerade f&uuml;r Textfelder noch eine schnelle Filterfunktion hinzuf&uuml;gen, mit der Sie sogar alle Datens&auml;tze anzeigen k&ouml;nnen, die den aktuell markierten Wert enthalten.<\/p>\n<p>Der Filter soll dann wie im Beispiel aus Bild 3 funktionieren. Der Benutzer markiert den Wert, nach dem die Daten gefiltert werden sollen, und klickt auf die Schaltfl&auml;che <b>Schneller Filter<\/b>. Daraufhin werden alle Datens&auml;tze ausgeblendet, deren Inhalt im betroffenen Feld nicht mit dem Vergleichswert &uuml;bereinstimmt. Eine weitere Schaltfl&auml;che soll den Filter wieder deaktivieren.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_01\/pic_1072_004.png\" alt=\"So soll der Filter nach einem Feldwert arbeiten.\" width=\"700\" height=\"327,9093\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: So soll der Filter nach einem Feldwert arbeiten.<\/span><\/b><\/p>\n<h2>Schaltfl&auml;che zum schnellen Filtern<\/h2>\n<p>Beginnen wir doch einfach mit einer Schaltfl&auml;che, die wir <b>cmdSchnellerFilter <\/b>nennen und mit der Beschriftung <b>Schneller Filter <\/b>versehen. Diese soll die Datenherkunft des Unterformulars in dem Formular, in dem sich die Schaltfl&auml;che befindet, nach dem Wert des zuvor markierten Feldes filtern. Wie sich herausstellt, ist dies gar nicht so einfach, denn wir finden erst gar nicht heraus, welches Feld gerade &uuml;berhaupt markiert war. <\/p>\n<p>Unsere erste Idee war es n&auml;mlich, das Steuerelement mit dem besagten Filtervergleichswert einfach &uuml;ber den Ausdruck <b>Screen.PreviousControl.Name <\/b>zu ermitteln und diesen per <b>Debug.Print <\/b>im Direktbereich auszugeben. Dazu haben wir die <b>Beim Klicken<\/b>-Ereignisprozedur der Schaltfl&auml;che <b>cmdSchnellerFilter <\/b>wie folgt ausgestattet:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdSchnellerFilter_Click()\r\n     <span style=\"color:blue;\">Debug.Print<\/span> Screen.PreviousControl.Name\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Das Ergebnis lieferte aber leider nicht das gesuchte Steuerelement, sondern den Namen des Unterformulars:<\/p>\n<pre>sfmArtikel_SchnellerFilter<\/pre>\n<h2>Zuletzt aktives Feld ermitteln<\/h2>\n<p>Wir stehen nun also vor dem Problem, zwar zum Zeitpunkt den Inhalt des zuletzt aktivierten Feldes im Unterformular zu ben&ouml;tigen, dieses aber nicht mehr zu kennen.<\/p>\n<p>Es gibt nun diverse M&ouml;glichkeiten, die gew&uuml;nschte Information zu erhalten. Eine davon lautet, irgendwo eine Variable vorzuhalten, die wir mit einem Verweis auf das jeweils aktive Steuerelement des Unterformulars f&uuml;llen und dann beim Mausklick auf die Schaltfl&auml;che <b>cmdSchnellerFilter <\/b>&uuml;ber diese Variable auf das Feld und seinen Inhalt zugreifen. Das ist allerdings mit einigem Aufwand verbunden, wenn wir es auf dem einfachen Weg erledigen. Dieser sieht vor, eine Variable zum Speichern des zuletzt verwendeten Feldes im Klassenmodul des Hauptformulars zu deklarieren. Au&szlig;erdem legen wir f&uuml;r jedes Steuerelement im Unterformular eine Ereigniseigenschaft namens <b>Bei Fokuserhalt <\/b>an und hinterlegen daf&uuml;r eine Ereignisprozedur, welche einen Verweis auf das jeweilige Steuerelement in die Variable im Klassenmodul des Hauptformulars eintr&auml;gt.<\/p>\n<p>Mit der Ereignisprozedur <b>Beim Klicken <\/b>der Schaltfl&auml;che <b>cmdSchnellerFilter <\/b>k&ouml;nnen Sie dann aus der Variablen den Wert ermitteln und nach dem Feld, an welches das Steuerelement aus der Variablen gebunden ist, filtern.<\/p>\n<p>Wir m&uuml;ssen nur f&uuml;r jedes betroffene Steuerelement im Unterformular eine entsprechende Ereignisprozedur f&uuml;r das Ereignis <b>Bei Fokuserhalt <\/b>hinterlegen. Und ebenso f&uuml;r alle Steuerelemente der Unterformulare in anderen Formularen, die Sie mit der Funktion ausstatten m&ouml;chten.<\/p>\n<h2>L&ouml;sung mit Klasse<\/h2>\n<p>Nun ist Access im Unternehmen aber weniger bekannt daf&uuml;r, den Leser mit Flei&szlig;arbeit auszustatten. Wir suchen eher nach einer L&ouml;sung, die der Leser in wenigen Minuten implementieren kann. Also greifen wir, wie schon ein paar Mal geschehen, auf Klassenmodule zur&uuml;ck, in denen wir die gew&uuml;nschte Funktionalit&auml;t unterbringen. Das Klassenmodul des Hauptformulars soll nur mit wenigen Zeilen Code ausgestattet werden, die zum gr&ouml;&szlig;ten Teil in der Ereignisprozedur <b>Form_Load <\/b>landen. Insgesamt sieht der ben&ouml;tigte Code wie folgt aus. Als Erstes ben&ouml;tigen wir eine Objektvariable, welche den Verweis auf die gleich noch erl&auml;uterte Klasse <b>clsFastFilter <\/b>aufnimmt:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objFastFilter<span style=\"color:blue;\"> As <\/span>clsFastFilter<\/pre>\n<p>Als N&auml;chstes folgt dann die Ereignisprozedur <b>Form_Load<\/b>, die wir folgt aussieht:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Set<\/span> objFastFilter = <span style=\"color:blue;\">New<\/span> clsFastFilter\r\n     <span style=\"color:blue;\">With<\/span> objFastFilter\r\n         <span style=\"color:blue;\">Set<\/span> .Subform = Me!sfmArtikel_SchnellerFilter.Form\r\n         <span style=\"color:blue;\">Set<\/span> .FastFilterButton = Me!cmdSchnellerFilter\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Sie erstellt zun&auml;chst ein neues Objekt auf Basis der Klasse  <b>clsFastFilter<\/b> und speichert den Verweis darauf in der Variablen <b>objFastFilter<\/b>. Dann weist sie den beiden Eigenschaften <b>Subform <\/b>und <b>FastFilterButton <\/b>Verweise auf das Unterformular mit den zu durchsuchenden Datens&auml;tzen (Achtung: <b><Unterformularname>.Form <\/b>liefert die richtige Referenz) und auf die Schaltfl&auml;che zu, welche den Filter erstellen soll. Zur Abrundung f&uuml;gen Sie noch eine Ereignisprozedur f&uuml;r die Schaltfl&auml;che mit der Beschriftung <b>Filter leeren <\/b>hinzu, welche schlicht den Filter des Unterformulars leert und somit wieder alle Datens&auml;tze anzeigt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdFilterLeeren_Click()\r\n     Me!sfmArtikel_SchnellerFilter.Form.Filter = \"\"\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Wichtige Vorbereitung<\/h2>\n<p>Wenn Sie Klassen erstellen, die Objekte wie etwa Formulare oder die enthaltenen Steuerelemente referenzieren und deren Ereignisse implementieren wollen, muss f&uuml;r das jeweilige Formular (und somit auch f&uuml;r Unterformulare) auch ein Klassenmodul vorliegen! In unserem Fall haben wir etwa f&uuml;r das Unterformular mit dem Datenblatt noch kein Klassenmodul angelegt. Dies erfolgt automatisch, sobald Sie f&uuml;r eine der Ereigniseigenschaften des Formulars ein Ereignis anlegen und dieses &uuml;ber die Schaltfl&auml;che mit den drei Punkten im VBA-Editor &ouml;ffnen. Sie k&ouml;nnen dies aber auch durch einfaches Einstellen der Eigenschaft <b>Enth&auml;lt Modul <\/b>erledigen. Diese Eigenschaft finden Sie im Reiter <b>Andere<\/b> des jeweiligen Formulars (s. Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_01\/pic_1072_003.png\" alt=\"Hinzuf&uuml;gen eines Klassenmoduls per Eigenschaft\" width=\"424,7115\" height=\"305,4576\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Hinzuf&uuml;gen eines Klassenmoduls per Eigenschaft<\/span><\/b><\/p>\n<h2>Die Klasse clsFastFilter<\/h2>\n<p>Diese Klasse ist die Steuerzentrale der L&ouml;sung. Sie nimmt die Verweise auf die beteiligten Elemente entgegen, also das Unterformular sowie die Schaltfl&auml;che zum Ausl&ouml;sen des Filters. Das Unterformular wird mit der folgenden Variablen referenziert, die im Kopf des Klassenmoduls deklariert wird:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Subform<span style=\"color:blue;\"> As <\/span>Form<\/pre>\n<p>Die Schaltfl&auml;che zum Ausl&ouml;sen des Filters landet per Verweis in dieser Variablen:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>WithEvents m_FastFilterButton<span style=\"color:blue;\"> As <\/span>CommandButton<\/pre>\n<p>Die Variable ist mit dem Schl&uuml;sselwort <b>WithEvents <\/b>deklariert, was daf&uuml;r sorgt, dass wir in diesem Klassenmodul Ereignisprozeduren f&uuml;r das Steuerelement implementieren k&ouml;nnen. Desweiteren ben&ouml;tigen wir noch zwei weitere Variablen. Die erste ist eine Collection und nimmt die Instanzen der Wrapper-Klassen auf, von denen wir f&uuml;r jedes filterbare Steuerelement eine erstellen und in die Collection schreiben:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>colControls<span style=\"color:blue;\"> As <\/span>Collection<\/pre>\n<p>Au&szlig;erdem brauchen wir noch die besagte Variable, welche das zuletzt durch den Benutzer angeklickte Steuerelement im Unterformular aufnimmt:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_CurrentControl<span style=\"color:blue;\"> As <\/span>Control<\/pre>\n<p>Damit die Wrapper-Objekte, die jeweils eines der gebundenen Steuerelemente im Unterformular aufnehmen, einen Verweis auf das zuletzt durch den Benutzer angeklickte Element in die Variable <b>m_CurrentControl <\/b>schreiben k&ouml;nnen, stellen wir eine <b>Property Set<\/b>-Methode in der Klasse <b>clsFastFilter <\/b>bereit, die wie folgt aussieht:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>CurrentControl(ctl<span style=\"color:blue;\"> As <\/span>Control)\r\n     <span style=\"color:blue;\">Set<\/span> m_CurrentControl = ctl\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Damit wir die Funktion, welche die Schaltfl&auml;che <b>cmdFastFilter <\/b>ausl&ouml;st, auch in der Klasse <b>clsFastFilter <\/b>unterbringen k&ouml;nnen und diese nicht in jedem neuen Formular erneut schreiben m&uuml;ssen, f&uuml;llen wir die lokale Variable <b>m_FastFilterButton <\/b>&uuml;ber die <b>Property Set<\/b>-Prozedur <b>FastFilterButton <\/b>mit einem Verweis auf die jeweilige Schaltfl&auml;che. Die Prozedur sieht so aus:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>FastFilterButton(cmd<span style=\"color:blue;\"> As <\/span>CommandButton)\r\n     <span style=\"color:blue;\">Set<\/span> m_FastFilterButton = cmd\r\n     cmd.OnClick = \"[Event Procedure]\"\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Sie erwartet einen Verweis auf die Schaltfl&auml;che als Parameter und tr&auml;gt diese in die Variable <b>m_FastFilterButton <\/b>ein. Au&szlig;erdem legt sie noch fest, dass in diesem Klassenmodul eine Implementierung des Ereignisses <b>OnClick <\/b>vorliegen k&ouml;nnte und beim Ausl&ouml;sen entsprechend ber&uuml;cksichtigt werden soll.<\/p>\n<p>Die Hauptarbeit in der Klasse &uuml;bernimmt die <b>Property Set<\/b>-Methode <b>Subform<\/b>, mit welcher die <b>Form_Load<\/b>-Ereignisprozedur der Klasse <b>clsFastFilter <\/b>das zu verwendende Unterformular zuweist. Sie erwartet das Formular als Parameter und sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>Subform(frm<span style=\"color:blue;\"> As <\/span>Form)\r\n     <span style=\"color:blue;\">Dim <\/span>ctl<span style=\"color:blue;\"> As <\/span>Control\r\n     <span style=\"color:blue;\">Dim <\/span>objFastFilterControl<span style=\"color:blue;\"> As <\/span>clsFastFilterControl\r\n     <span style=\"color:blue;\">Dim <\/span>strControlSource<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> m_Subform = frm\r\n     <span style=\"color:blue;\">Set<\/span> colControls = <span style=\"color:blue;\">New<\/span> Collection\r\n     For Each ctl In m_Subform.Controls\r\n         strControlSource = \"\"\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         strControlSource = ctl.ControlSource\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strControlSource) &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> objFastFilterControl =  <span style=\"color:blue;\">New<\/span> clsFastFilterControl\r\n             <span style=\"color:blue;\">With<\/span> objFastFilterControl\r\n                 <span style=\"color:blue;\">Set<\/span> .Control = ctl\r\n                 <span style=\"color:blue;\">Set<\/span> .MyParent = Me\r\n                 colControls.Add objFastFilterControl\r\n             End <span style=\"color:blue;\">With<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> ctl\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Die Prozedur stellt zun&auml;chst die Variable <b>m_Subform <\/b>auf das &uuml;bergebene Formular ein. Dann instanziert sie eine neue Collection und speichert diese in der Variablen <b>colControls<\/b>. Schlie&szlig;lich durchl&auml;uft sie alle Steuerelemente des mit <b>frm <\/b>angegebenen Unterformulars. In der daf&uuml;r verwendeten <b>For Each<\/b>-Schleife pr&uuml;ft die Prozedur, ob es sich beim aktuell durchlaufenen Steuerelement &uuml;berhaupt um ein gebundenes Steuerelement handelt. Andere Steuerelemente wie etwa Bezeichnungsfelder brauchen wir gar nicht zu ber&uuml;cksichtigen. Dazu leert die Prozedur eine Variable namens <b>strControlSource <\/b>und versucht dann, diese bei deaktivierter Fehlerbehandlung mit dem Wert der Eigenschaft <b>ControlSource <\/b>des aktuellen Steuerelements aus <b>ctl <\/b>zu f&uuml;llen. Enth&auml;lt <b>strControlSource <\/b>danach keine leere Zeichenkette, handelt es sich um ein gebundenes Steuerelement und es kann in Form des Wrapper-Objekts auf Basis der Klasse <b>clsFastFilterControl <\/b>referenziert und zur Collection <b>colControls <\/b>hinzugef&uuml;gt werden.  Dann erstellt die Prozedur ein neues Objekt auf Basis von <b>clsFastFilterControl<\/b>, f&uuml;llt dessen Eigenschaft <b>Control <\/b>mit einem Verweis auf das aktuelle Steuerelement und die Eigenschaft <b>MyParent <\/b>mit einem Verweis auf sich selbst, also die Instanz der Klasse <b>clsFastFilter<\/b>. Wozu dies n&ouml;tig ist, erfahren Sie gleich bei der Beschreibung der Klasse <b>clsFastFilterControl<\/b>. Nun m&uuml;ssen wir nur noch daf&uuml;r sorgen, dass das Wrapper-Objekt, das ja lokal innerhalb der <b>Property Set<\/b>-Prozedur deklariert wurde und anderenfalls mit dem Ende der Prozedur erl&ouml;schen w&uuml;rde, nicht im Nirwana verschwindet. Dazu f&uuml;gt die Prozedur es zur Collection <b>colControls <\/b>hinzu.<\/p>\n<p>Gehen wir an dieser Stelle vereinfachend davon aus, dass  die Wrapper-Objekte beim Anklicken durch den Benutzer daf&uuml;r sorgen, dass ein Verweis auf das angeklickte gebundene Steuerelement in der Variablen <b>m_CurrentControl <\/b>landet.<\/p>\n<p>Dann k&ouml;nnen wir uns die Ereignisprozedur ansehen, die durch einen Mausklick auf die mit der Variablen <b>m_FastFilterButton<\/b> referenzierte Schaltfl&auml;che ausgel&ouml;st wird. Die Prozedur sieht wie in Listing 1 aus. Sie liest zun&auml;chst den Namen des Feldes, das dem mit der Variablen <b>m_CurrentControl <\/b>referenzierten und zuletzt durch den Benutzer angeklickten Steuerelement angeh&ouml;rt, in die Variable <b>strControlSource <\/b>ein.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>m_FastFilterButton_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Dim <\/span>strControlSource<span style=\"color:blue;\"> As String<\/span>\r\n     strControlSource = m_CurrentControl.ControlSource\r\n     <span style=\"color:blue;\">Set<\/span> rst = m_Subform.Recordset\r\n     Select Case rst.Fields(strControlSource).Type\r\n         <span style=\"color:blue;\">Case <\/span>dbText\r\n             m_Subform.Filter = strControlSource & \" = ''\" _\r\n                 & <span style=\"color:blue;\">Replace<\/span>(m_CurrentControl.Value, \"''\", \"''''\") & \"''\"\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n        <span style=\"color:blue;\">Case <\/span>dbDate\r\n             m_Subform.Filter = strControlSource & \" = \" & CDbl(m_CurrentControl.Value)\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Case Else<\/span>\r\n             m_Subform.Filter = strControlSource & \" = \" & m_CurrentControl.Value\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Implementierung des Beim Klicken-Ereignisses der Filter-Schaltfl&auml;che<\/span><\/b><\/p>\n<p>Dann f&uuml;llt sie eine <b>Recordset<\/b>-Variable namens <b>rst <\/b>mit dem Recordset des zu filternden Unterformulars. Sie ermittelt dann f&uuml;r das Element der <b>Fields<\/b>-Auflistung mit dem Namen aus <b>strControlsource <\/b>den Datentyp und gleicht diesen in einer <b>Select Case<\/b>-Bedingung mit verschiedenen Werten ab. Wir haben hier nur <b>dbText <\/b>f&uuml;r Textfelder, <b>dbDate <\/b>f&uuml;r Datumsfelder und alle &uuml;brigen Datentypen untersucht, obwohl hier noch weitere Unterscheidungen m&ouml;glich w&auml;ren. Im Falle des Wertes <b>dbText <\/b>stellt die folgende Anweisung einen Vergleichsausdruck zusammen, der aus dem Feldnamen aus <b>strControlSource<\/b>, dem Gleichheitszeichen und dem in Hochkommata eingefassten Wert des Steuerelements aus <b>m_CurrentControl <\/b>besteht, also etwa <b>Artikelname = &#8220;Chai&#8220;<\/b>. Dieser Vergleichsausdruck landet in der Eigenschaft <b>Filter <\/b>des Unterformulars. Das Einstellen einer weiteren Eigenschaft namens <b>FilterOn <\/b>auf den Wert <b>True <\/b>sorgt schlie&szlig;lich daf&uuml;r, dass der Filter auch auf die aktuellen Daten angewendet wird.<\/p>\n<p><!--30percent--><\/p>\n<p>Wichtig ist an dieser Stelle noch der Hinweis auf das eventuelle Auftreten von Hochkommata oder Anf&uuml;hrungszeichen innerhalb der Zeichenkette. Diese f&uuml;hren beim Zusammensetzen des Filterausdrucks zu Fehlern, was nicht geschieht, wenn Sie diese verdoppeln &#8211; in diesem Fall durch entsprechenden Einsatz der <b>Replace<\/b>-Funktion.<\/p>\n<p>Im Falle eines Datums w&uuml;rde, wenn wir dieses einfach wie eine Zahl behandeln, ein Ausdruck wie <b>Auslaufdatum = 1.1.2016 <\/b>verwendet, was zu einem Fehler f&uuml;hrt. Daher wandeln wir den Wert des Datumsfeldes zuvor mit der <b>CDbl<\/b>-Funktion in einen <b>Double<\/b>-Wert um, der dann keinen Fehler mehr ausl&ouml;st.<\/p>\n<p>F&uuml;r alle &uuml;brigen Datentypen soll einfach das Feld mit dem jeweiligen Wert verglichen werden.<\/p>\n<h2>Die Klasse clsFastFilterControl<\/h2>\n<p>Es fehlt noch ein genauerer Blick auf die Klasse <b>clsFastFilterControl<\/b>. Diese wird f&uuml;r jedes gebundene Steuerelement im Unterformular genau einmal instanziert, denn wir wollen ja f&uuml;r jedes dieser Steuerelemente das Ereignis <b>Bei Fokuserhalt <\/b>implementieren, um dort das aktuelle Steuer-element in der Variablen <b>m_CurrentControl <\/b>des Objekts basierend auf der Klasse <b>clsFastFilter <\/b>zu speichern.<\/p>\n<p>Die Klasse <b>clsFastFilterControl <\/b>soll zun&auml;chst einmal einen Verweis auf das erstellende Objekt speichern, hier also das Objekt auf Basis der Klasse <b>clsFastFilter<\/b>. Dazu verwenden wir die folgende Variable:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Parent<span style=\"color:blue;\"> As <\/span>clsFastFilter<\/pre>\n<p>Die ben&ouml;tigte <b>Property Set<\/b>-Methode sieht so aus:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>MyParent(obj<span style=\"color:blue;\"> As <\/span>clsFastFilter)\r\n     <span style=\"color:blue;\">Set<\/span> m_Parent = obj\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Au&szlig;erdem wollen wir bei den Steuerelementen des Datenblatts unter den Steuerelementtypen Textfeld, Kombinationsfeld und Kontrollk&auml;stchen unterscheiden (andere Steuerelemente machen im Datenblatt auch keinen Sinn). Daher deklarieren wir die folgenden drei Variablen innerhalb der Klasse, da wir ja noch nicht wissen, welchen Steuerelementtyp die Klasse aufnehmen soll:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>WithEvents txt<span style=\"color:blue;\"> As <\/span>TextBox\r\n<span style=\"color:blue;\">Private <\/span>WithEvents cbo<span style=\"color:blue;\"> As <\/span>ComboBox\r\n<span style=\"color:blue;\">Private <\/span>WithEvents chk<span style=\"color:blue;\"> As <\/span>CheckBox<\/pre>\n<p>Nun fehlt noch die <b>Property Set<\/b>-Methode, die das zu untersuchende Steuerelement entgegennimmt und einige weitere Schritte durchf&uuml;hrt. Diese sieht wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>Control(ctl<span style=\"color:blue;\"> As <\/span>Control)\r\n     Select Case ctl.ControlType\r\n         <span style=\"color:blue;\">Case <\/span>acTextBox\r\n             <span style=\"color:blue;\">Set<\/span> txt = ctl\r\n             txt.OnGotFocus = \"[Event Procedure]\"\r\n         <span style=\"color:blue;\">Case <\/span>acComboBox\r\n             <span style=\"color:blue;\">Set<\/span> cbo = ctl\r\n             cbo.OnGotFocus = \"[Event Procedure]\"\r\n         <span style=\"color:blue;\">Case <\/span>acCheckBox\r\n             <span style=\"color:blue;\">Set<\/span> chk = ctl\r\n             chk.OnGotFocus = \"[Event Procedure]\"\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Die Prozedur pr&uuml;ft zun&auml;chst anhand der Eigenschaft <b>ControlType<\/b>, um welchen Typ es sich handelt. Im Falle von <b>acTextBox <\/b>f&uuml;llt sie beispielsweise die Variable <b>txt <\/b>mit einem Verweis auf das mit dem Parameter <b>ctl <\/b>gelieferte Steuerelement. Au&szlig;erdem stellt sie die Eigenschaft <b>OnGotFocus <\/b>auf den Wert <b>[Event Procedure] <\/b>ein, was im Eigenschaftsfenster des Formulars dem Einstellen der Eigenschaft <b>Bei Fokuserhalt <\/b>auf <b>[Ereignisprozedur] <\/b>entspricht. F&uuml;r die beiden anderen Typen, die mit den Konstanten <b>dbComboBox <\/b>und <b>dbCheckBox <\/b>gepr&uuml;ft werden, verl&auml;uft dies &auml;hnlich. Schlie&szlig;lich m&uuml;ssen wir noch das Ereignis <b>Bei Fokuserhalt <\/b>f&uuml;r die drei deklarierten Objektvariablen f&uuml;r die drei Steuerelementtypen <b>Textfeld<\/b>, <b>Kombinationsfeld <\/b>und <b>Kontrollk&auml;stchen <\/b>implementieren, was wir wie folgt erledigen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cbo_GotFocus()\r\n     <span style=\"color:blue;\">Set<\/span> m_Parent.CurrentControl = cbo\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>chk_GotFocus()\r\n     <span style=\"color:blue;\">Set<\/span> m_Parent.CurrentControl = chk\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>txt_GotFocus()\r\n     <span style=\"color:blue;\">Set<\/span> m_Parent.CurrentControl = txt\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>In diesen drei Prozeduren weisen wir jeweils der Eigenschaft <b>CurrentControl <\/b>des in <b>m_Parent <\/b>gespeicherten Objekts (also unsere Instanz der Klasse <b>clsFastFilter<\/b>) eine Referenz auf das ausl&ouml;sende Steuerelement zu, die dann wiederum in der Variablen <b>m_CurrentControl <\/b>der Klasse <b>clsFastFilter <\/b>landet. Damit ist die Programmierung der grundlegenden Funktion bereits erledigt: Wir k&ouml;nnen das Datenblatt nun nach den Werten einzelner Felder filtern.<\/p>\n<h2>Filtern nach &#8222;Enth&auml;lt &#8230;&#8220;<\/h2>\n<p>F&uuml;r den Einsatz mit Textfeldern w&auml;re es noch interessant, wenn wir auch Vergleiche mit Teilausdr&uuml;cken erlauben w&uuml;rden. Wie w&auml;re es etwa, wenn Sie nur ein paar Buchstaben des Feldinhalts eines Textfeldes markieren und danach in allen Datens&auml;tzen suchen wollten Das w&auml;re schon praktisch, also machen wir uns an die Arbeit. Zu diesem Zweck f&uuml;gen wir dem Formular eine weitere Schaltfl&auml;che namens <b>cmdSchnellerFilterTeilausdruck <\/b>hinzu. Die Prozedur <b>Form_Load<\/b> erweitern wir entsprechend um die Zuweisung dieser Schaltfl&auml;che zur gleich noch anzulegenden Eigenschaft in der Klasse <b>clsFast-Filter<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Set<\/span> objFastFilter = <span style=\"color:blue;\">New<\/span> clsFastFilter\r\n     <span style=\"color:blue;\">With<\/span> objFastFilter\r\n         ...\r\n         <span style=\"color:blue;\">Set<\/span> .FastFilterContainsButton =  Me!cmdSchnellerFilterTeilausdruck\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Klasse <b>clsFastFilter <\/b>erh&auml;lt eine neue Variable zum Speichern der Schaltfl&auml;che:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>WithEvents m_FastFilterContainsButton <span style=\"color:blue;\"> As <\/span>CommandButton<\/pre>\n<p>Um diese Schaltfl&auml;che der Variablen zuzuweisen, ben&ouml;tigen wir eine entsprechende Property Set-Prozedur:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>FastFilterContainsButton( cmd<span style=\"color:blue;\"> As <\/span>CommandButton)\r\n     <span style=\"color:blue;\">Set<\/span> m_FastFilterContainsButton = cmd\r\n     <span style=\"color:blue;\">With<\/span> cmd\r\n         .OnClick = \"[Event Procedure]\"\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Im gleichen Zuge f&uuml;gen wir eine Variable hinzu, welche die Teilzeichenkette speichert:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_Searchstring<span style=\"color:blue;\"> As String<\/span><\/pre>\n<p>Um diese einzustellen, legen wir eine &ouml;ffentliche Eigenschaft per <b>Property Let<\/b>-Prozedur fest:<\/p>\n<pre><span style=\"color:blue;\">Public Property Let <\/span>Searchstring(str<span style=\"color:blue;\"> As String<\/span>)\r\n     m_Searchstring = str\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Damit die Schaltfl&auml;che <b>cmdSchnellerFilterTeilausdruck <\/b>auch etwas bewirkt, legen wir die Ereignisprozedur aus Listing 2 in der Klasse <b>clsFastFilter <\/b>an. Diese ber&uuml;cksichtigt nur Steuerelemente, deren gebundenes Feld den Felddatentyp <b>dbText <\/b>aufweist. F&uuml;r diese stellt es einen Vergleichsausdruck zusammen, der aus dem Feldnamen, dem <b>LIKE<\/b>-Operator sowie dem Vergleichswert besteht. Dieser stammt aus der Variablen <b>m_Searchstring<\/b>, bei dem eventuell enthaltene Hochkommata verdoppelt wurden. Der Vergleichswert wird au&szlig;erdem in Sternchen und einfache Anf&uuml;hrungszeichen eingeschlossen. Wenn der Benutzer nun etwa die Zeichenkette <b>an <\/b>des Artikels <b>Chang <\/b>markiert und auf die Schaltfl&auml;che klickt, soll der Filterausdruck so aussehen:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>m_FastFilterContainsButton_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strControlSource<span style=\"color:blue;\"> As String<\/span>\r\n     strControlSource = m_CurrentControl.ControlSource\r\n     <span style=\"color:blue;\">Set<\/span> rst = m_Subform.Recordset\r\n     Select Case rst.Fields(strControlSource).Type\r\n         <span style=\"color:blue;\">Case <\/span>dbText\r\n             m_Subform.Filter = strControlSource & \" LIKE ''*\" & <span style=\"color:blue;\">Replace<\/span>(m_Searchstring, \"''\", \"''''\") & \"*''\"\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Case Else<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Dieses Feature funktioniert nur mit Textfeldern.\"\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Implementierung des Beim Klicken-Ereignisses der Schaltfl&auml;che cmdSchnellerFilterTeilausdruck<\/span><\/b><\/p>\n<pre>Artikelname LIKE ''*an*''<\/pre>\n<p>Das Ergebnis sieht dann etwa wie in Bild 5 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_01\/pic_1072_005.png\" alt=\"Filtern nach einem Teilausdruck einer Zeichenkette\" width=\"649,559\" height=\"424,4643\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Filtern nach einem Teilausdruck einer Zeichenkette<\/span><\/b><\/p>\n<h2>Erweiterung der Klasse clsFastFilterControl<\/h2>\n<p>Eine Kleinigkeit fehlt nat&uuml;rlich noch: Wir m&uuml;ssen noch daf&uuml;r sorgen, dass nach der Markierung eines Teilausschnitts eines Textfeldes auch der entsprechende Ausschnitt in der Variablen <b>m_Searchstring <\/b>der Klasse <b>clsFastFilter <\/b>landet. Leider k&ouml;nnen wir die notwendigen Zeilen nicht in der Ereignisprozedur <b>txt_GotFocus <\/b>unterbringen, die ja bereits das zuletzt aktive Steuerelement in die Variable <b>m_CurrentControl <\/b>eintr&auml;gt. Der Grund ist, dass dieses Ereignis ja bereits beim Fokuserhalt des Textfeldes ausgel&ouml;st wird und nicht erst, wenn der Benutzer den gew&uuml;nschten Ausschnitt markiert hat. Welches andere  Ereignis k&ouml;nnen wir daf&uuml;r nutzen <b>Bei Fokusverlust <\/b>w&auml;re eine erste Idee, aber die hilft nicht weiter, weil das <b>Beim Klicken<\/b>-Ereignis der Schaltfl&auml;che vorher feuert. Also m&uuml;ssen wir ein wenig mehr ins Detail gehen und die Maus- und Tastatur-Ereignisse hinzuziehen. Der Abschluss einer Markierung wird immer entweder mit dem Loslassen der Maustaste oder der Tastatur abgeschlossen. Also nutzen wir einfach die beiden Ereignisse <b>Bei Maustaste auf <\/b>und <b>Bei Taste auf<\/b>.<\/p>\n<p>Zun&auml;chst f&uuml;llen wir die entsprechenden Ereignisprozeduren in der <b>Property Set<\/b>-Prozedur <b>Control<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>Control(ctl<span style=\"color:blue;\"> As <\/span>Control)\r\n     Select Case ctl.ControlType\r\n         <span style=\"color:blue;\">Case <\/span>acTextBox\r\n             <span style=\"color:blue;\">Set<\/span> txt = ctl\r\n             txt.OnGotFocus = \"[Event Procedure]\"\r\n             txt.OnKeyUp = \"[Event Procedure]\"\r\n             txt.OnMouseUp = \"[Event Procedure]\"\r\n         ''...\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Die beiden Ereignisprozeduren sehen nun wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>txt_KeyUp(KeyCode<span style=\"color:blue;\"> As Integer<\/span>, Shift<span style=\"color:blue;\"> As Integer<\/span>)\r\n     SetSearchstring\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>txt_MouseUp(Button<span style=\"color:blue;\"> As Integer<\/span>,  Shift<span style=\"color:blue;\"> As Integer<\/span>, X<span style=\"color:blue;\"> As Single<\/span>, Y<span style=\"color:blue;\"> As Single<\/span>)\r\n     SetSearchstring\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Beide w&uuml;rden die gleichen Anweisungen enthalten, also haben wir diese in die Prozedur <b>SetSearchstring <\/b>ausgelagert:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>SetSearchstring()\r\n     <span style=\"color:blue;\">If <\/span>txt.SelLength &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         m_Parent.Searchstring = <span style=\"color:blue;\">Mid<\/span>(txt.Value,  txt.SelStart + 1, txt.SelLength)\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         m_Parent.Searchstring = Nz(txt.Value, \"\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Prozedur pr&uuml;ft anhand des Wertes der Eigenschaft <b>SelLength <\/b>des Textfeldes, ob &uuml;berhaupt eine Markierung vorliegt. Falls ja, tr&auml;gt sie f&uuml;r die Eigenschaft <b>SearchString <\/b>der Klasse <b>clsFastFilter <\/b>eine Zeichenkette ein, die dem markierten Text entspricht. Diesen ermitteln wir, indem wir vom kompletten Text des Textfeldes den Teil mit der <b>Mid<\/b>-Funktion auslesen, der an der Position des Starts der Markierung beginnt (<b>txt.SelStart + 1<\/b>) und die L&auml;nge der Markierung aufweist (<b>txt.SelLength<\/b>).<\/p>\n<p>Sollte keine Markierung im Text vorhanden sein, landet einfach der komplette Text in der Eigenschaft <b>SearchString <\/b>der Klasse <b>clsFastFilter <\/b>und somit in der Variablen <b>m_SearchString <\/b>dieser Klasse.<\/p>\n<h2>Filtern nach Zeichenketten von Lookupfeldern<\/h2>\n<p>Machen wir es nun ein wenig interessanter: Wir wollen nun auch nach Teilzeichenketten in Kombinationsfeldern suchen. So m&ouml;chten wir also beispielsweise alle Lieferanten anzeigen, deren Name mit <b>A <\/b>beginnt. Wie dies gelingt, sehen Sie in der Beispieldatenbank. Die grundlegende Technik erl&auml;utern wir im Beitrag <b>Lookup-Kombinationsfelder nach Texten filtern <\/b>(<b>www.access-im-unternehmen.de\/1071<\/b>).<\/p>\n<p>In unserem Fall m&uuml;ssen wir zun&auml;chst die Klasse <b>clsFastFilterControl <\/b>so erweitern, dass auch Kombinationsfelder die Ereignisse <b>Bei Taste auf <\/b>und <b>Bei Maustaste auf <\/b>ausl&ouml;sen. Dazu erweitern wir die Property Set-Prozedur Control wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>Control(ctl<span style=\"color:blue;\"> As <\/span>Control)\r\n     Select Case ctl.ControlType\r\n         ...\r\n         <span style=\"color:blue;\">Case <\/span>acComboBox\r\n             <span style=\"color:blue;\">Set<\/span> cbo = ctl\r\n             cbo.OnGotFocus = \"[Event Procedure]\"\r\n             cbo.OnKeyUp = \"[Event Procedure]\"\r\n             cbo.OnMouseUp = \"[Event Procedure]\"\r\n             ...\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Diese beiden Ereignisprozeduren implementieren Sie wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cbo_KeyUp(KeyCode<span style=\"color:blue;\"> As Integer<\/span>, Shift<span style=\"color:blue;\"> As Integer<\/span>)\r\n     SetSearchstringComboBox\r\n<span style=\"color:blue;\">End Sub<\/span>\r\n<span style=\"color:blue;\">Private Sub <\/span>cbo_MouseUp(Button<span style=\"color:blue;\"> As Integer<\/span>,  Shift<span style=\"color:blue;\"> As Integer<\/span>, X<span style=\"color:blue;\"> As Single<\/span>, Y<span style=\"color:blue;\"> As Single<\/span>)\r\n     SetSearchstringComboBox\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Wie Sie sehen, verwenden wir hier den Methodennamen <b>SetSearchstringComboBox<\/b>, wo wir bei den entsprechenden Methoden f&uuml;r die Textfelder nur <b>SetSearchstring <\/b>genutzt haben. Dementsprechend benennen wir <b>SetSearchstring <\/b>in <b>SetSearchstringTextbox <\/b>um (und passen die Aufrufe an).<\/p>\n<p>Die Prozedur <b>SetSearchstringComboBox <\/b>sieht wie in Listing 3 aus. Sie pr&uuml;ft, ob das Kombinationsfeld eine Markierung enth&auml;lt oder nicht. Im ersten Fall stellt sie den Wert der Eigenschaft <b>Searchstring <\/b>der Klasse <b>clsFastFilter <\/b>mithilfe der Funktion <b>LookupSearchstring<\/b> zusammen, die wir im oben genannten Beitrag ausf&uuml;hrlich abbilden und erl&auml;utern. Der <b>Searchstring<\/b> enth&auml;lt dabei unkonsequenterweise nicht mehr nur den Vergleichswert wie etwa <b>*Ge*<\/b>, sondern gleich den kompletten Filterausdruck wie folgt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>SetSearchstringCombobox()\r\n     <span style=\"color:blue;\">If <\/span>cbo.SelLength &gt; 0<span style=\"color:blue;\"> Then<\/span>\r\n         m_Parent.Searchstring = LookupSearchstring(cbo, \"*\" & <span style=\"color:blue;\">Mid<\/span>(cbo.Text, cbo.SelStart + 1, cbo.SelLength) & \"*\")\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         m_Parent.Searchstring = LookupSearchstring(cbo, \"*\" & Nz(cbo.Text, \"\") & \"*\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Methode zum Zusammenstellen des Filterausdrucks f&uuml;r ein Kombinationsfeld mit markierter Teilzeichenfolge<\/span><\/b><\/p>\n<pre>KategorieID IN (SELECT KategorieID FROM tblKategorien WHERE Kategoriename LIKE ''*Ge*'')<\/pre>\n<p>Diese kleine Ungenauigkeit gleichen wir in der Anpassung der Prozedur <b>m_FastFilterContainsButton_Click <\/b>wieder aus (s. Listing 4). Hier haben wir die Pr&uuml;fung, ob es sich bei dem gepr&uuml;ften Feld um eines mit dem Datentyp <b>dbText <\/b>handelt, durch eine andere Pr&uuml;fung ersetzt. Nun untersuchen wir den Steuerelementtyp des Steuerelements aus dem Unterformular, das zum Zeitpunkt des Klicks auf die Schaltfl&auml;che aus <b>m_FastFilterContainsButton <\/b>aktiv war. Im Falle einer Textbox &auml;ndert sich nichts, wir verwenden die bereits zuvor f&uuml;r den Fall des Datentyps <b>acText <\/b>genutzten Anweisungen. Wenn es sich jedoch um ein Kombinationsfeld handelt (<b>acComboBox<\/b>), dann stellt die Prozedur nicht wie beim Textfeld erst den Filterausdruck zusammen, sondern &uuml;bernimmt diesen direkt komplett aus der Variablen <b>m_Searchstring <\/b>und tr&auml;gt diesen in die Eigenschaft <b>Filter <\/b>ein, bevor dieser mit <b>FilterOn = True <\/b>aktiviert wird.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>m_FastFilterContainsButton_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strControlSource<span style=\"color:blue;\"> As String<\/span>\r\n     strControlSource = m_CurrentControl.ControlSource\r\n     <span style=\"color:blue;\">Set<\/span> rst = m_Subform.Recordset\r\n     Select Case m_CurrentControl.ControlType\r\n         <span style=\"color:blue;\">Case <\/span>acTextBox\r\n             m_Subform.Filter = strControlSource & \" LIKE ''*\" _\r\n                 & <span style=\"color:blue;\">Replace<\/span>(m_Searchstring, \"''\", \"''''\") & \"*''\"\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Case <\/span>acComboBox\r\n             m_Subform.Filter = m_Searchstring\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Erweiterung der Ereignisprozedur f&uuml;r FastFilterContainsButton<\/span><\/b><\/p>\n<h2>Weitere M&ouml;glichkeiten: Filter kombinieren<\/h2>\n<p>Nun stellt sich die Frage, ob wir diese hilfreichen Filterausdr&uuml;cke nicht auch in Kombination nutzen k&ouml;nnen. Bislang ersetzen wir den Wert der Eigenschaft <b>Filter<\/b> des Unterformulars immer durch den neuen Wert, aber ber&uuml;cksichtigen den vorherigen Wert nicht mehr. Wie cool w&auml;re es denn, wenn wir entscheiden k&ouml;nnten, ob wir den Filter neu setzen oder aber diesen per AND- oder OR-Parameter mit dem bestehenden Filter verkn&uuml;pfen<\/p>\n<p>Wir m&uuml;ssten allerdings vorher noch einige Modalit&auml;ten festlegen. Die erste ist: Wollen wir die Verkn&uuml;pfung per <b>AND <\/b>oder <b>OR <\/b>oder sogar beide M&ouml;glichkeiten bereitstellen Wenn wir nur eine der beiden anbieten, k&ouml;nnen wir die einzelnen Bedingungen einfach durch das entsprechende Schl&uuml;sselwort voneinander getrennt aneinanderh&auml;ngen. Wenn wir sowohl <b>AND <\/b>als auch <b>OR <\/b>bereitstellen wollen, m&uuml;ssen wir uns &uuml;berlegen, wie die Priorit&auml;t gesetzt wird. Wenn der Benutzer willk&uuml;rlich <b>AND <\/b>und <b>OR <\/b>durcheinandermischt, liefert dies vermutlich nur schwer kontrollierbare Ergebnisse. Also lassen wir diese Variante direkt au&szlig;en vor.<\/p>\n<p>Die zweite &uuml;berlegung ist: Wie soll der Benutzer uns mitteilen, ob er die aktuell hinzuzuf&uuml;gende Bedingung zus&auml;tzlich zur bestehenden Bedingung nutzen oder die bestehende Bedingung ersetzen m&ouml;chte<\/p>\n<p>Am einfachsten ist wohl ein Kontrollk&auml;stchen, mit dem der Benutzer den Modus einstellen kann. Dies erledigen wir, indem wir einfach ein Kontrollk&auml;stchen namens <b>chkFilterKombinieren <\/b>hinzuf&uuml;gen.<\/p>\n<p>Ein zweites Steuerelement k&ouml;nnte dem Benutzer erm&ouml;glichen, festzulegen, ob er mit <b>AND <\/b>oder <b>OR <\/b>verkn&uuml;pfen m&ouml;chte. Dazu eignet sich wohl am besten eine Optionsgruppe namens <b>ogrANDOrOR <\/b>mit zwei entsprechenden Optionsschaltfl&auml;chen.<\/p>\n<p>Im Entwurf sieht das Formular nun wie in Bild 6 aus. Das Kontrollk&auml;stchen <b>chkFilterKombinieren <\/b>erh&auml;lt den Standardwert <b>False<\/b>. Die Optionsgruppe erh&auml;lt den Standardwert <b>1 <\/b>(die beiden Optionen sollen die Werte <b>1 <\/b>und <b>2 <\/b>aufweisen).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_01\/pic_1072_006.png\" alt=\"Steuerelemente zur Angabe, ob Filterausdr&uuml;cke kombiniert werden sollen\" width=\"700\" height=\"142,4243\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Steuerelemente zur Angabe, ob Filterausdr&uuml;cke kombiniert werden sollen<\/span><\/b><\/p>\n<p>Damit die Optionsgruppe deaktiviert ist, wenn das Kontrollk&auml;stchen <b>chkFilterKombinieren <\/b>den Wert <b>False <\/b>enth&auml;lt, legen wir folgende Ereignisprozedur an, die durch das Ereignis <b>Nach Aktualisierung <\/b>des Kontrollk&auml;stchens ausgel&ouml;st wird:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>chkFilterKombinieren_AfterUpdate()\r\n     Me!ogrANDOrOR.Enabled = Me!chkFilterKombinieren\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Der Klasse <b>clsFastFilter <\/b>f&uuml;gen wir zwei Variablen hinzu, mit denen wir die beiden neuen Steuerelemente referenzieren k&ouml;nnen:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_CombineFilter<span style=\"color:blue;\"> As <\/span>CheckBox\r\n<span style=\"color:blue;\">Private <\/span>m_ANDOrOR<span style=\"color:blue;\"> As <\/span>OptionGroup<\/pre>\n<p>Diese Variablen k&ouml;nnen vom instanzierenden Formular &uuml;ber die folgenden beiden <b>Property Set<\/b>-Eigenschaften zugewiesen werden:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>CombineFilterCheckbox(chk<span style=\"color:blue;\"> As <\/span>CheckBox)\r\n     <span style=\"color:blue;\">Set<\/span> m_CombineFilter = chk\r\n<span style=\"color:blue;\">End Property<\/span>\r\n<span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>ANDOrOROptiongroup(ogr<span style=\"color:blue;\"> As <\/span>OptionGroup)\r\n     <span style=\"color:blue;\">Set<\/span> m_ANDOrOR = ogr\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Nun passen wir als Erstes die Ereignisprozedur <b>m_FastFilterButton_Click<\/b> an, die ja die Filterausdr&uuml;cke f&uuml;r komplette Inhalte zusammenstellt. Die neue Version finden Sie in Listing 5.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>m_FastFilterButton_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strControlSource<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFilter<span style=\"color:blue;\"> As String<\/span>\r\n     strControlSource = m_CurrentControl.ControlSource\r\n     <span style=\"color:blue;\">Set<\/span> rst = m_Subform.Recordset\r\n     Select Case rst.Fields(strControlSource).Type\r\n         <span style=\"color:blue;\">Case <\/span>dbText\r\n             strFilter = strControlSource & \" = ''\" & <span style=\"color:blue;\">Replace<\/span>(m_CurrentControl.Value, \"''\", \"''''\") & \"''\"\r\n             m_Subform.Filter = CombineFilter(strFilter)\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Case <\/span>dbDate\r\n             strFilter = strControlSource & \" = \" & CDbl(m_CurrentControl.Value)\r\n             m_Subform.Filter = CombineFilter(strFilter)\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Case Else<\/span>\r\n             strFilter = strControlSource & \" = \" & m_CurrentControl.Value\r\n             m_Subform.Filter = CombineFilter(strFilter)\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Angepasste Version der Methode m_FastFilterButton_Click f&uuml;r kombinierte Filter<\/span><\/b><\/p>\n<p>Die Prozedur ermittelt nach wie vor den Namen des gebundenen Feldes des zum Zeitpunkt der Bet&auml;tigung der Schaltfl&auml;che aktiven Steuerelements im Unterformular und f&uuml;llt eine <b>Recordset<\/b>-Variable mit dem Recordset des Unterformulars. Dann pr&uuml;ft es den Datentyp des enthaltenen Feldes und stellt den Filterausdruck zusammen. Dieser landet jedoch nicht direkt in der Eigenschaft <b>Filter <\/b>des Unterformulars, sondern in der Variablen <b>strFilter<\/b>.<\/p>\n<p>Bevor der Filterausdruck angewendet wird, m&uuml;ssen Sie noch pr&uuml;fen, ob die <b>Filter<\/b>-Eigenschaft bereits einen Filterausdruck enth&auml;lt, und den neuen Ausdruck gegebenenfalls an den bestehenden Ausdruck anh&auml;ngen. Dies erledigen wir mit der Funktion <b>CombineFilter <\/b>aus Listing 6. Diese erwartet lediglich den neuen Filterausdruck aus <b>strFilter <\/b>als Parameter.<\/p>\n<pre><span style=\"color:blue;\">Private Function <\/span>CombineFilter(strFilter<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strANDOrOR<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">If <\/span>m_CombineFilter Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n         CombineFilter = strFilter\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> m_CombineFilter<span style=\"color:blue;\"> Then<\/span>\r\n             CombineFilter = strFilter\r\n         <span style=\"color:blue;\">Else<\/span>\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(m_Subform.Filter) = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">If <\/span>m_ANDOrOR = 1<span style=\"color:blue;\"> Then<\/span>\r\n                     strANDOrOR = \" AND \"\r\n                 <span style=\"color:blue;\">Else<\/span>\r\n                     strANDOrOR = \" OR \"\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             CombineFilter = m_Subform.Filter & strANDOrOR & strFilter\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Diese Funktion f&uuml;gt Filterausdr&uuml;cke zusammen<\/span><\/b><\/p>\n<p>Sie pr&uuml;ft zun&auml;chst, ob die Variable <b>m_CombineFilter <\/b>&uuml;berhaupt gef&uuml;llt ist &#8211; denn es kann ja auch sein, dass der Entwickler dieses Feature f&uuml;r das aktuelle Formular gar nicht implementiert und somit kein entsprechendes Kontrollk&auml;stchen angegeben hat. Anderenfalls untersucht die Funktion, ob das in der Variablen <b>m_CombineFilter <\/b>referenzierte Steuerelement den Wert <b>False <\/b>enth&auml;lt, was der Fall ist, wenn der Benutzer das Kontrollk&auml;stchen <b>chkFilterKombinieren <\/b>nicht auf den Wert <b>True <\/b>eingestellt hat.<\/p>\n<p>Ist <b>m_CombineFilter <\/b>also <b>False<\/b>, dann wird der R&uuml;ckgabewert der Funktion einfach mit dem Inhalt von <b>strFilter <\/b>gef&uuml;llt. Dieser landet dann in der Prozedur <b>m_FastFilterButton <\/b>in der <b>Filter<\/b>-Eigenschaft des Unterformulars, woraufhin nur noch der Filter mit <b>FilterOn = True <\/b>aktiviert werden muss.<\/p>\n<p>Es kann jedoch auch geschehen, dass der Benutzer das Kontrollk&auml;stchen <b>chkFilterKombinieren <\/b>aktiviert hat. In diesem Fall kommt der zweite Teil der <b>If&#8230;Then<\/b>-Bedingung in der Funktion <b>CombineFilter <\/b>zum Einsatz. Hier pr&uuml;ft die Funktion zuerst, ob f&uuml;r das Unterformular bereits ein Filter festgelegt wurde (<b>Len(m_Subform.Filter) = 0<\/b>). Falls ja, untersucht die n&auml;chste <b>If&#8230;Then<\/b>-Bedingung, ob der Benutzer die Filter-Bedingungen mit <b>AND <\/b>oder <b>OR <\/b>verkn&uuml;pfen m&ouml;chte. Die daf&uuml;r ben&ouml;tigte Information finden wir in der Variablen <b>m_ANDOrOR<\/b>, die wiederum aus der Optionsgruppe <b>ogrANDOrOR <\/b>gef&uuml;llt wird. Ist dort der Wert <b>1 <\/b>eingestellt, soll der <b>AND<\/b>-Operator verwendet werden, sonst der <b>OR<\/b>-Operator.<\/p>\n<p>Im jeweiligen Fall wird einer der beiden Operatoren in die Variable <b>strANDOrOR <\/b>eingetragen. Diese landet sp&auml;ter wiederum als Bestandteil des neuen, kombinierten Ausdrucks in der Variablen <b>CombineFilter<\/b>, die gleichzeitig als R&uuml;ckgabewert der Funktion dient.<\/p>\n<p>Von der Ereignisprozedur <b>m_FastFilterContainsButton_Click<\/b>, die in unserem Beispiel beim Klick auf die Schaltfl&auml;che <b>cmdSchnellerFilterTeilausdruck <\/b>ausgel&ouml;st wird, rufen wir die Funktion <b>CombineFilter <\/b>auf die gleiche Weise auf und stellen damit den Filterausdruck zusammen (s. Listing 7). Wir k&ouml;nnen so also auch die beiden unterschiedlichen Schaltfl&auml;chen zur Definition von Filterausdr&uuml;cken miteinander kombinieren.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>m_FastFilterContainsButton_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strControlSource<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strFilter<span style=\"color:blue;\"> As String<\/span>\r\n     strControlSource = m_CurrentControl.ControlSource\r\n     <span style=\"color:blue;\">Set<\/span> rst = m_Subform.Recordset\r\n     Select Case m_CurrentControl.ControlType\r\n         <span style=\"color:blue;\">Case <\/span>acTextBox\r\n             strFilter = strControlSource & \" LIKE ''*\" _\r\n                 & <span style=\"color:blue;\">Replace<\/span>(m_Searchstring, \"''\", \"''''\") & \"*''\"\r\n             m_Subform.Filter = CombineFilter(strFilter)\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Case <\/span>acComboBox\r\n             strFilter = m_Searchstring\r\n             m_Subform.Filter = CombineFilter(strFilter)\r\n             m_Subform.FilterOn = <span style=\"color:blue;\">True<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Angepasste Version der Methode m_FastFilterContainsButton_OK f&uuml;r kombinierte Filter<\/span><\/b><\/p>\n<h2>Warum zwei Schaltfl&auml;chen<\/h2>\n<p>Eines aber st&ouml;rt noch: Warum sollen wir &uuml;berhaupt mit zwei Schaltfl&auml;chen arbeiten &#8211; immerhin k&ouml;nnte man doch auch pr&uuml;fen, ob der Benutzer die Einf&uuml;gemarke einfach nur in das Feld gesetzt hat, um mit dem kompletten Ausdruck zu vergleichen, oder ob er einen Teil des Textes markiert hat<\/p>\n<p>Der Grund ist, dass die beiden Schaltfl&auml;chen ja nicht nur erstens komplette Eintr&auml;ge und zweitens Teileintr&auml;ge zum Filter hinzuf&uuml;gen sollen, sondern die zweite Schaltfl&auml;che f&uuml;r die Teileintr&auml;ge stellt ja auch einen Filter ein, nach dem nur die Elemente durchsucht werden, die den Teilausdruck enthalten und nicht komplett mit ihm &uuml;bereinstimmen.<\/p>\n<h2>SQL-Ausdruck anzeigen<\/h2>\n<p>Zur Orientierung der Benutzer k&ouml;nnte man den aktuellen Filter noch in einem Textfeld anzeigen, das beispielsweise oberhalb des Datenblatts platziert ist (s. Bild 7).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2017_01\/pic_1072_007.png\" alt=\"Textfeld, das den aktuellen Filterausdruck anzeigt\" width=\"649,559\" height=\"179,2868\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Textfeld, das den aktuellen Filterausdruck anzeigt<\/span><\/b><\/p>\n<p>Dieses Textfeld ber&uuml;cksichtigen wir wieder mit einer entsprechenden Variablen in der Klasse <b>clsFastFilter<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Private <\/span>m_FilterTextbox<span style=\"color:blue;\"> As <\/span>TextBox<\/pre>\n<p>Dort legen wir auch die <b>Property Set<\/b>-Eigenschaft fest:<\/p>\n<pre><span style=\"color:blue;\">Public Property <span style=\"color:blue;\">Set<\/span> <\/span>FilterTextbox(txt<span style=\"color:blue;\"> As <\/span>TextBox)\r\n     <span style=\"color:blue;\">Set<\/span> m_FilterTextbox = txt\r\n     txt.Enabled = <span style=\"color:blue;\">False<\/span>\r\n     txt.Locked = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Property<\/span><\/pre>\n<p>Damit das Textfeld mit dem Filterausdruck gef&uuml;llt wird, f&uuml;gen wir zu den beiden Ereignisprozeduren <b>m_FastFilterButton_Click <\/b>und <b>m_FastFilterContainsButton_Click <\/b>die folgenden Zeilen am Ende hinzu:<\/p>\n<pre><span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> m_FilterTextbox Is Nothing<span style=\"color:blue;\"> Then<\/span>\r\n     m_FilterTextbox = m_Subform.Filter\r\n<span style=\"color:blue;\">End If<\/span><\/pre>\n<h2>L&ouml;sung einsetzen<\/h2>\n<p>Wenn Sie diese L&ouml;sung in eigenen Anwendungen einsetzen wollen, f&uuml;gen Sie die beiden Klassen <b>clsFastFilter <\/b>und <b>clsFastFilterControl <\/b>zur Anwendung hinzu.<\/p>\n<p>Au&szlig;erdem ben&ouml;tigen Sie ein Formular mit den folgenden Steuerelementen:<\/p>\n<ul>\n<li>Unterformular, das gefiltert werden soll, in der Datenblattansicht<\/li>\n<li>Schaltfl&auml;che zum Filtern nach dem kompletten Feldinhalt<\/li>\n<li>Schaltfl&auml;che zum Filtern nach einem Teilinhalt (optional)<\/li>\n<li>Schaltfl&auml;che zum Leeren des Filters (optional)<\/li>\n<li>Kontrollk&auml;stchen zur Angabe, ob Filter kombiniert werden sollen (optional)<\/li>\n<li>Optionsgruppe, mit der AND oder OR festgelegt wird (optional)<\/li>\n<li>Textfeld zur Ausgabe des Filterausdrucks (optional)<\/li>\n<\/ul>\n<p>Die Steuerelemente legen Sie dann in der <b>Beim Laden<\/b>-Ereignisprozedur des Formulars fest. Beispiele finden Sie in den Formularen <b>frmKunden<\/b>, <b>frmArtikel <\/b>und <b>frmPersonal <\/b>(Letzteres verwendet beispielsweise die Minimalkonfiguration). Davon abgesehen m&uuml;ssen Sie nur die Objektvariable f&uuml;r die Klasse <b>clsFastFilter <\/b>deklarieren &#8211; hier in der minimalen Einstellung:<\/p>\n<pre><span style=\"color:blue;\">Dim <\/span>objFastFilter<span style=\"color:blue;\"> As <\/span>clsFastFilter\r\n<span style=\"color:blue;\">Private Sub <\/span>Form_Load()\r\n     <span style=\"color:blue;\">Set<\/span> objFastFilter = <span style=\"color:blue;\">New<\/span> clsFastFilter\r\n     <span style=\"color:blue;\">With<\/span> objFastFilter\r\n         <span style=\"color:blue;\">Set<\/span> .FastFilterButton = Me!cmdFiltern\r\n         <span style=\"color:blue;\">Set<\/span> .Subform = Me!sfmPersonal.Form\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Dieser Beitrag zeigt eine L&ouml;sung, mit der Sie einem Formular samt Unterformular eine schnelle M&ouml;glichkeit zum Filtern des Unterformular-Inhalts nach den dort enthaltenen Werten hinzuf&uuml;gen k&ouml;nnen. Dank der Kapselung der Funktionalit&auml;t in eine Klasse sind nur wenige Zeilen Code n&ouml;tig, um die Features zum Formular hinzuzuf&uuml;gen.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>SchnellerFilter.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/687C5884-5B72-44F2-851E-CC6A1F744AD7\/aiu_1072.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Formulare in der Datenblattansicht bieten alles Filter- und Sortierm&ouml;glichkeiten, die das Benutzerherz begehrt. Allerdings sind diese nicht unbedingt immer schnell erreichbar &#8211; hier und da k&ouml;nnte es noch ein wenig fixer gehen. Ein Beispiel ist ein Filter, der nur die Datens&auml;tze anzeigt, die den Wert des aktuell markierten Feldes im jeweiligen Feld enthalten. Wenn Sie also etwa eine Reihe von Artikeln anzeigen, die einer bestimmten Kategorie angeh&ouml;ren und schnell nur noch die Artikel dieser Kategorie sehen wollen, ben&ouml;tigen Sie dazu mehrere Mausklicks. Dieser Beitrag zeigt, wie Sie verschiedene Suchen mit einem einfachen Klick auf eine Schaltfl&auml;che erledigen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66012017,662017,44000023],"tags":[],"class_list":["post-55001072","post","type-post","status-publish","format-standard","hentry","category-66012017","category-662017","category-Mit_Formularen_arbeiten"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Schneller Filter - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Schneller Filter\" \/>\n<meta property=\"og:description\" content=\"Formulare in der Datenblattansicht bieten alles Filter- und Sortierm&ouml;glichkeiten, die das Benutzerherz begehrt. Allerdings sind diese nicht unbedingt immer schnell erreichbar - hier und da k&ouml;nnte es noch ein wenig fixer gehen. Ein Beispiel ist ein Filter, der nur die Datens&auml;tze anzeigt, die den Wert des aktuell markierten Feldes im jeweiligen Feld enthalten. Wenn Sie also etwa eine Reihe von Artikeln anzeigen, die einer bestimmten Kategorie angeh&ouml;ren und schnell nur noch die Artikel dieser Kategorie sehen wollen, ben&ouml;tigen Sie dazu mehrere Mausklicks. Dieser Beitrag zeigt, wie Sie verschiedene Suchen mit einem einfachen Klick auf eine Schaltfl&auml;che erledigen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-14T13:41:07+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg09.met.vgwort.de\/na\/4fbbc500170f4967a2d4d8f4b2734958\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"30\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Schneller Filter\",\"datePublished\":\"2020-05-14T13:41:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/\"},\"wordCount\":4969,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/4fbbc500170f4967a2d4d8f4b2734958\",\"articleSection\":[\"1\\\/2017\",\"2017\",\"Mit Formularen arbeiten\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/\",\"name\":\"Schneller Filter - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/4fbbc500170f4967a2d4d8f4b2734958\",\"datePublished\":\"2020-05-14T13:41:07+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/4fbbc500170f4967a2d4d8f4b2734958\",\"contentUrl\":\"http:\\\/\\\/vg09.met.vgwort.de\\\/na\\\/4fbbc500170f4967a2d4d8f4b2734958\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Schneller_Filter\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Schneller Filter\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Schneller Filter - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/","og_locale":"de_DE","og_type":"article","og_title":"Schneller Filter","og_description":"Formulare in der Datenblattansicht bieten alles Filter- und Sortierm&ouml;glichkeiten, die das Benutzerherz begehrt. Allerdings sind diese nicht unbedingt immer schnell erreichbar - hier und da k&ouml;nnte es noch ein wenig fixer gehen. Ein Beispiel ist ein Filter, der nur die Datens&auml;tze anzeigt, die den Wert des aktuell markierten Feldes im jeweiligen Feld enthalten. Wenn Sie also etwa eine Reihe von Artikeln anzeigen, die einer bestimmten Kategorie angeh&ouml;ren und schnell nur noch die Artikel dieser Kategorie sehen wollen, ben&ouml;tigen Sie dazu mehrere Mausklicks. Dieser Beitrag zeigt, wie Sie verschiedene Suchen mit einem einfachen Klick auf eine Schaltfl&auml;che erledigen.","og_url":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-14T13:41:07+00:00","og_image":[{"url":"http:\/\/vg09.met.vgwort.de\/na\/4fbbc500170f4967a2d4d8f4b2734958","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"30\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Schneller Filter","datePublished":"2020-05-14T13:41:07+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/"},"wordCount":4969,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/4fbbc500170f4967a2d4d8f4b2734958","articleSection":["1\/2017","2017","Mit Formularen arbeiten"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Schneller_Filter\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/","url":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/","name":"Schneller Filter - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/#primaryimage"},"thumbnailUrl":"http:\/\/vg09.met.vgwort.de\/na\/4fbbc500170f4967a2d4d8f4b2734958","datePublished":"2020-05-14T13:41:07+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Schneller_Filter\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/#primaryimage","url":"http:\/\/vg09.met.vgwort.de\/na\/4fbbc500170f4967a2d4d8f4b2734958","contentUrl":"http:\/\/vg09.met.vgwort.de\/na\/4fbbc500170f4967a2d4d8f4b2734958"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Schneller_Filter\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Schneller Filter"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001072","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55001072"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001072\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001072"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001072"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001072"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}