Seite 1 von 3

FilterStringBuilder & Co.

BeitragVerfasst: Di 28. Jan 2014, 11:39
von Josef Pötzl
Hallo!

Falls mal jemand Lust hat, ein paar Klassen zu testen: in der Codelib gibt es nun eine Klassenstruktur zum Erstellen von Filterbedingungen.

SqlTools (Klasse): umgestaltetes SqlTools.bas-Codemodul, damit mehrere SQL-Dialekte parallel verwenden werden können. (Attribute VB_PredeclaredId = True ist gesetzt - damit ist immer eine Standardinstanz verfügbar. Der Import ohne ACLibImportWizard oder ACLibFilterFormWizard muss über Datei-Import erfolgen, damit dieses Attribut gesetzt wird. Beim Einfügen des Codes in eine leere Klasse muss man das selbst einstellen, falls man es nutzen will.)

FilterStringBuilder: Filterausdruck als String erzeugen.

FilterControlManager: Filterausdruck direkt aus Formular-Steuerelementen erstellen

Beispiel-DB: FilterStringBuilderBsp

Zum Einfügen in eine Anwendung gibt es das Add-In: ACLibFilterFormWizard

BTW: Wenn das Interface für die Access-Klassenstruktur einigermaßen steht, möchte ich die Funktionaltät in der DotNetLib abbilden und mit den AccessCodeLib.Data.SqlTools kombinieren.


Mögliche Varianten:
Stufe 1: nur Datentyp in Sql-tauglichen Text umwandeln.
Code: Alles auswählen
SqlText = "TextDatenfeld like " & SqlTools.TextToSqlText("ab'de*")
' oder
SqlText = "DatumsDatenfeld = " & SqlTools.DateToSqlText(Date)
' oder
SqlText = "ZahlenDatenfeld = " & SqlTools.NumberToSqlText(1.234)

Anm.: Die SqlTools-Standardinstanz muss vor der ersten Verwendung an den benötigten SQL-Dialekt angepasst oder innerhalb der Klasse die Konfigurations-Konstanten eingestellt werden.

Stufe 2: BuildCriteria verwenden
Code: Alles auswählen
SqlText = SqlTools.BuildCriteria("TextDatenfeld", SQL_Text, SQL_Like, "ab'de*")
' oder
SqlText = SqlTools.BuildCriteria("DatumsDatenfeld", SQL_Date, SQL_Equal, Date)
' oder
SqlText = SqlTools.BuildCriteria("ZahlenDatenfeld", SQL_Numeric, SQL_Equal, 1.234)


Stufe 3: Zusammengesetzten SQL-Filter-Ausdruck mit FilterStringBuilder erstellen:
Code: Alles auswählen
With New FilterStringBuilder
   .Add "TextDatenfeld", SQL_Text, SQL_Like, "ab'de*"
   .Add "DatumsDatenfeld", SQL_Date, SQL_Equal, Date
   .Add "ZahlenDatenfeld", SQL_Numeric, SQL_Equal, 1.234
   SqlText = .ToString(SQL_And)
End With


Stufe 4: Die Filtersteuerung in einem Formular an den FilterControlManager abgeben.
Code: Alles auswählen
Private WithEvents m_FilterControlManager As FilterControlManager
[...]
Private Sub InitFilterControls()
   With m_FilterControlManager.FilterControls
      .Add "TextDatenfeld", SQL_Text, SQL_Like, Me.txtFilterControlTextDatenfeld
      .Add "DatumsDatenfeld", SQL_Date, SQL_Equal, Me.txtFilterControlDatumsDatenfeld
      .Add "ZahlenDatenfeld", SQL_Numeric, SQL_Equal, Me.txtFilterControlZahlenDatenfeld
   End With
End Sub
 

mfg
Josef

Re: FilterStringBuilder & Co.

BeitragVerfasst: Di 11. Feb 2014, 12:57
von Josef Pötzl
Mögliche Varianten mit SqlTools.BuildCriteria

Equal & Co. ... =, >, <
Code: Alles auswählen
     ' F = 'abc'
     Sql = .BuildCriteria("F", SQL_Text, SQL_Equal, "abc")
     ' F <= 123
     Sql = .BuildCriteria("F", SQL_Numeric, SQL_Equal + SQL_LessThan, 123)
     ' F >= #2014-01-01#
     Sql = .BuildCriteria("F", SQL_Date, SQL_Equal + SQL_GreaterThan, #1/1/2014#)
   
     ' Spezialfälle:
     ' <= + SQL_Add_WildCardSuffix zum Kennzeichnen des "ganzen Tages" obwohl nur Datum ohne Uhrzeit übergeben wird
     ' F <= #2013-12-31*#  =>  F < #2014-01-01
     Sql = .BuildCriteria("F", SQL_Date, SQL_Equal + SQL_LessThan + SQL_Add_WildCardSuffix, #12/31/2013#)

Like
Code: Alles auswählen
     ' F like 'abc*'
     Sql = .BuildCriteria("F", SQL_Text, SQL_Like + SQL_Add_WildCardSuffix, "abc")
     ' F like '*abc*'
     Sql = .BuildCriteria("F", SQL_Text, SQL_Like + SQL_Add_WildCardSuffix + SQL_Add_WildCardPrefix, "abc")

Between
Code: Alles auswählen
     ' F Between 123 And 456
     Sql = .BuildCriteria("F", SQL_Numeric, SQL_Between, 123, 456)

     ' F Between #2014-01-01# And #2014-01-31#
     Sql = .BuildCriteria("F", SQL_Date, SQL_Between, #1/1/2014#, #1/31/2014#)

     ' Spezialfälle:
     ' SQL_Between + SQL_Add_WildCardSuffix zum Kennzeichnen des "ganzen Tages"
     ' F Between #2013-01-01# And #2013-12-31*# =>  F >= #2013-01-01# And F < #2014-01-01#
     Sql = .BuildCriteria("F", SQL_Date, SQL_Between + SQL_Add_WildCardSuffix, #1/1/2013#, #12/31/2013#)

Or ... mehrere Werte auf das gleiche Datenfeld
Code: Alles auswählen
     ' F like 'a*' Or F like 'c*' Or F like 'e*'
     Sql = .BuildCriteria("F", SQL_Text, SQL_Like + SQL_Add_WildCardSuffix, Array("a", "c", "e"))
     ' F = 123 Or F = 456 Or F = 789  (Anm.: diese Variante könnte man eventuell auch als In(..)-Statement darstellen.)
     Sql = .BuildCriteria("F", SQL_Numeric, SQL_Equal, Array(123, 456, 789))
     

In(...)
Code: Alles auswählen
     ' F In (123,456,789)
     Sql = .BuildCriteria("F", SQL_Numeric, SQL_In, Array(123, 456, 789))
     ' F In ('a','b','c')
     Sql = .BuildCriteria("F", SQL_Text, SQL_In, Array("a", "b", "c"))


Was fehlt noch?

Re: FilterStringBuilder & Co.

BeitragVerfasst: Fr 15. Mai 2015, 21:46
von Josef Pötzl
Update: SqlTools.cls und FilterStringBuilder.cls sind nun im trunk enthalten und somit die Schnittstelle fixiert.

Re: FilterStringBuilder & Co.

BeitragVerfasst: Sa 26. Sep 2015, 18:17
von Josef Pötzl
Nächste Ausbaustufe: .net-dll

NetLibFilterStringBuilderBsp.zip
(132.91 KiB) 1770-mal heruntergeladen


Anm.:
Vor der ersten Verwendung/Test bitte das Formular "DotNetLibRepair" öffnen. Dann werden die notwendigen dll-Dateien aus der Tabelle usys_AppFiles exportiert und die Verweise angepasst.
Die Beispiel-DB ist noch nicht vollständig umgestellt, da der FilterControlManager noch nicht in .net implementiert wurde.

Der .net-ConditionStringBuilder entspricht ungefähr dem VBA-FilterStringBuilder.

Änderung in der Schnittstelle:
VBA / FilterStringBuilder:
Code: Alles auswählen
Public Sub Add(ByVal FieldName As String, ByVal FieldDataType As SqlFieldDataType, _
               ByVal RelationalOperator As SqlRelationalOperators, _
               ByVal Value As Variant, _
      Optional ByVal Value2 As Variant = Null, _
      Optional ByVal IgnoreValue As Variant = Null)


Value2 wird nur für Between benötigt.
Diesen Parameter entfernte ich in der .net-Variante und verwende stattdessen eine Array-Übergabe mit 2 Werten.

Anwendungsbeispiel:
FilterStringBuilder (VBA-Klasse):
Code: Alles auswählen
.Add "NumericField", SQL_Numeric, SQL_Between, 133.45, 456


ConditionSTringBuilder (.net-Klasse):
Code: Alles auswählen
.Add "NumericField", FieldDataType_Numeric, SQL_Between, Array(133.45, 456)


Grund für diese Änderung: ich wollte nur für den Beetween-Operator keinen Parameter mitziehen, der sonst nie benötigt wird.
Allerdings werde ich in der .net-Klasse noch eine Methode AddBetween anfügen, damit man auf das Array verzichten kann.
=>
Code: Alles auswählen
.AddBetween "NumericField", FieldDataType_Numeric, 133.45, 456

Re: FilterStringBuilder & Co.

BeitragVerfasst: So 27. Sep 2015, 10:31
von Andreas Vogt
Hallo,
gebe ich bei Z3 von 3 bis 2 ein, was ja imho unsinnig ist, kommt im Formular frm_CreateFilterString Z3 Between 3 And 2 raus,
während im Formular frm_CreateFilterStringFilterControls Z3 Between 2 And 3 raus kommt.

Andreas

Re: FilterStringBuilder & Co.

BeitragVerfasst: Mo 28. Sep 2015, 08:46
von Josef Pötzl
Hallo!

Das ist ein Fehler im Formular. ;)
statt
Code: Alles auswählen
.Add "Z3", SQL_Numeric, SQL_Between, Me.txtFilterZB2, Me.txtFilterZB1

sollte stehen:
Code: Alles auswählen
.Add "Z3", SQL_Numeric, SQL_Between, Me.txtFilterZB1, Me.txtFilterZB2


Aber daraus abgeleitet eine Frage:
Sollte man die Werte vertauschen, damit ein auswertbarer Between-Ausdruck entsteht?

Welche Variante ist besser?
Das Between-Statement so erzeugen, wie es vom Anwendungsersteller bzw. Anwender eingegeben wird oder die Werte vertauschen, damit nicht between 3 and 2 entsteht?

LG
Josef

Re: FilterStringBuilder & Co.

BeitragVerfasst: Mo 28. Sep 2015, 13:13
von Andreas Vogt
Hallo,
die Parameter können ja nicht nur aus "Handeingabe" stammen sondern auch z.B. aus Berechnung stammen.
Ich finde schon die Funktion sollte so arbeiten mit den Parametern wie übergeben. Wenn von 3 bis 2 raus kommt ist die Ergebnismenge halt 0.

Andreas

Re: FilterStringBuilder & Co.

BeitragVerfasst: Mo 28. Sep 2015, 17:33
von Josef Pötzl
Hallo!
Ich finde schon die Funktion sollte so arbeiten mit den Parametern wie übergeben.

Ich sehe das genau so, weil damit das vom Anwendungsersteller zu erwartende Verhalten bleibt.

Anm.:
Neue Beispiel-DB:
NetLibFilterStringBuilderBsp.zip
(132.91 KiB) 1753-mal heruntergeladen

... nun arbeiten die FilterControl-Klassen auch mit der .net-Bibliothek.

LG
Josef

Re: FilterStringBuilder & Co.

BeitragVerfasst: Sa 10. Okt 2015, 14:52
von Josef Pötzl
Eine neue Version des ACLib-FilterForm-Wizard ist verfügbar.

Neu: Der Code for das Filterformular enthält nun alles, was man zum filtern benötigt. Anpassen ist nur noch für spezielle Filterbedingungen notwendig.

LG
Josef

Re: FilterStringBuilder & Co.

BeitragVerfasst: Di 20. Okt 2015, 13:38
von Josef Pötzl
Nächstes Feature: Filterbedingungen gruppieren (z. B. für Or-Gruppe)

Beispiel:
Code: Alles auswählen
With New FilterStringBuilder

   Set .SqlTool = SqlTools.NewInstance("\#yyyy-mm-dd\#", "True", "*")

   .Add "F1", SQL_Numeric, SQL_Equal, 1
   
   With .NewConditionGroup(SQL_Or)
      .Add "F2a", SQL_Text, SQL_Like + SQL_Add_WildCardSuffix, "a"
      .Add "F2b", SQL_Text, SQL_Like + SQL_Add_WildCardSuffix, "a"
      .Add "F2c", SQL_Text, SQL_Like + SQL_Add_WildCardSuffix, "a"
   End With

   With .NewConditionGroup(SQL_Or)
      .Add "F3a", SQL_Boolean, SQL_Equal, True
      .Add "F3b", SQL_Boolean, SQL_Equal, True
      .Add "F3c", SQL_Boolean, SQL_Equal, True
   End With

   Debug.Print .ToString(SQL_And)

End With


Ergebnis:
((F1 = 1)) And ((F2a Like 'a*') Or (F2b Like 'a*') Or (F2c Like 'a*')) And ((F3a = True) Or (F3b = True) Or (F3c = True))