User Tools

Site Tools


vba:flexiblerfilter

[VBA] flexible Filter

Häufig hat man mehrere Filterfelder in einem Formularkopf definiert. Je nachdem was alles ausgefüllt ist, ist der Filter Komplexer oder nicht. Auf alle Fälle muss es sehr flexibel sein. Hier einige Anregungen.

Grundsätzlich sollte nie ein Filtererstellungscode direkt hinter einen Event eines Controls geschrieben werden. Immer in eine eigene Sub, die dann von mehreren Orten aufgerufen werden kann.

Ausgangslage

Als Beispiel nehmen wir ein Formular mit 3 Filter.

1) Ein Textfeld für die Adresse:
Formularfeld: txtAddress
Tabellenfeld: address
DataType: String

2) Eine Combobox. Inkl. einem Eintrag “-1” und der Beschriftung “ALL”
Formularfeld: cbxAddressType
Tabellenfeld: addressTypeId
DataType: Long

3) 2 Datumsfelder für ein Between
Formularfeld: dtFrom, dtTo
Tabellenfeld: createDate
DataType: Date

Der Klassiker

Ich persönlich mag den gar nicht. Aber man sieht ihn häufig. Alle Strings einfach zusammensetzen und dann schauen, ob am Ende vom String noch ein “ AND ” steht. Dieses dann abschneiden

Privat Sub createFilter()
    Dim flt As String
    If NZ(me!txtAddress) <> "" Then
        flt = "address LIKE '" & me!txtAddress & "' AND "
    End If
    If NZ(me!cbxAddressType, -1) > -1 Then
        flt = "addressTypeId = " & me!cbxAddressType & " AND "
    End If
    If Not IsNull(Me!dtFrom) And Not IsNull(Me.dtTo) Then
        flt = ftl & "createDate BETWEEN " & format(me!dtFrom, "\#MM-DD-YYYY\#") & " AND " & format(me!dtTo, "\#MM-DD-YYYY\#")        
    End If
    'ggf das " AND " am Ende Abschneiden
    If right(flt, 5) = " AND " Then
        flt = left(flt, len(flt) - 5) 
    End If
 
    'Filter setzen'
    If len(flt) > 0 Then
        Me.Filter = flt
        Me.FilterOn = True
    Else
        Me.Filter = Empty
        Me.FilterOn = False
    End If
End Sub

Mittels Array

Der Umweg über einen Array finde ich persönlich schöner.

Privat Sub createFilter()
    Dim flt() as String
    Dim i As Long: i = -1
    If NZ(me!txtAddress) <> "" Then
        i = i + 1:  Redim Preserve flt(i)
        flt(i) = "address LIKE '" & me!txtAddress & "'"
    End If
    If NZ(me!cbxAddressType, -1) > -1 Then
        i = i + 1:  Redim Preserve flt(i)
        flt(i) = "addressTypeId = " & me!cbxAddressType
    End If
    If Not IsNull(Me!dtFrom) And Not IsNull(Me.dtTo) Then
        i = i + 1:  Redim Preserve flt(i)
        flt(i) = ftl & "createDate BETWEEN " & format(me!dtFrom, "\#MM-DD-YYYY\#") & " AND " & format(me!dtTo, "\#MM-DD-YYYY\#")        
    End If
 
    'Fitler setzen
    If i > -1 Then
        Me.Filter = join(flt, " AND ")
        Me.FilterOn = True
    Else
        Me.Filter = Empty
        Me.FilterOn = False
    End If
End Sub

Über meinen YFilter

Und um es möglichst einfach zuhalten, hatte ich mal den [VBA] YFilter programmiert. Damit lassens ich Filter relativ einfach erstellen

Privat Sub createFilter()
    Dim flt As YFilter
    Set flt = YFilter.createAnd
    If NZ(me!txtAddress) <> "" Then flt.addNewFilter("address", me!txtAddress, eftLike)
    If NZ(me!cbxAddressType, -1) > -1 Then flt.addNewFilter("addressTypeId", me!cbxAddressType)
    If Not IsNull(Me!dtFrom) And Not IsNull(Me.dtTo) Then flt.addNewFilter("createDate", array(me!dtFrom, me!dtTo))
 
    Me.Filter = flt.filterText
    Me.FilterOn = flt.isActive
End Sub
vba/flexiblerfilter.txt · Last modified: 29.01.2019 08:36:08 by yaslaw