Bindingsource.Filter | Filterbezeichnung mit Wildcard durch String Interpolation ersetzten

  • VB.NET
  • .NET 4.5

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    Bindingsource.Filter | Filterbezeichnung mit Wildcard durch String Interpolation ersetzten

    Hallo
    Ich habe eine FilterX Methoe mit Wildcards (hier im Code auskommentiert). Diese funktioniert.
    Ich möchte diese aber durch eine Version mit String Interpolation umsetzten. Da ich den Filterausdruck als String an eine Funktion übergebe.
    Diese kann die beiden Variablen StartDate und EndDate nicht verarbeiten.
    Aber das schmeißt mir den Fehler: System.Data.SyntaxErrorException: "Das Token '.' kann an Position 27 nicht interpretiert werden."
    Der Filterausdruck sieht zur Zeit des Fehlers so aus: bs.Filter"LastCalculationSP >= 03.06.2021 00:00:00 And LastCalculationSP <= 03.06.2021 23:59:00"String

    VB.NET-Quellcode

    1. Private Sub CBSPChange_CheckedChanged(sender As Object, e As EventArgs) Handles CBSPChange.CheckedChanged
    2. Dim StartDate As Date = New Date(DTPStart.Value.Year, DTPStart.Value.Month, DTPStart.Value.Day, 0, 0, 0)
    3. Dim EndDate As Date = New Date(DTPEnd.Value.Year, DTPEnd.Value.Month, DTPEnd.Value.Day, 23, 59, 0)
    4. 'ArticleBindingSource.FilterX("LastCalculationSP >= ? And LastCalculationSP <= ?", StartDate, EndDate)
    5. ArticleBindingSource.FilterX($"LastCalculationSP >= {StartDate} And LastCalculationSP <= {EndDate}")
    6. End Sub


    Was habe ich falsch gemacht?
    Probier mal so: $"LastCalculationSP >= {StartDate:yyyy-MM-dd} And LastCalculationSP <= {EndDate:yyyy-MM-dd}"

    Oder Du fragst mal den Hersteller dieser FilterX-Methode, was das Problem ist.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hmm, hiermit bekomme ich dann den Fehler, dass die Operation <= nicht an System.DateTime angewendet werden kann.
    Der Erfinder dieser Methode ist leider gerade nicht aktiv.
    ICh hau mal die Methode hier rein. Vielleicht sieht da einer durch :)

    VB.NET-Quellcode

    1. ​Public Sub FilterX(bs As BindingSource, expression As String, ParamArray values() As Object)
    2. Dim filter = GetFilterString(expression, values)
    3. bs.Filter = If(bs.Filter = filter, "", filter) ' GetFilterString(expression, values)
    4. End Sub
    5. Private Function GetFilterString(expression As String, values() As Object) As String
    6. Dim splits = expression.Split("?"c) ' identify placeholder '?'
    7. If splits.Count > values.Length + 1 Then Throw New ArgumentException( _
    8. "expression contains more placeholders than values are passed")
    9. For i = 0 To splits.Length - 2
    10. Dim val = values(i)
    11. Dim sb = New Text.StringBuilder("{0}")
    12. If TypeOf (val) Is Date Then
    13. sb.Insert(0, "#"c).Append("#"c)
    14. ElseIf TypeOf (val) Is String Then
    15. With splits(i)
    16. If .EndsWith("*") Then sb.Insert(0, "*"c) : splits(i) = .Remove(.Length - 1, 1)
    17. End With
    18. With splits(i + 1)
    19. If .StartsWith("*") Then sb.Append("*"c) : splits(i + 1) = .Remove(0, 1)
    20. End With
    21. sb.Insert(0, "'"c).Append("'"c)
    22. End If
    23. splits(i) &= String.Format(Globalization.CultureInfo.InvariantCulture, sb.ToString, val)
    24. Next
    25. Return String.Concat(splits)
    26. End Function

    DerSmurf schrieb:

    Da ich den Filterausdruck als String an eine Funktion übergebe.

    Das musst du mir bitte erklären... Also bitte mal ein Beispiel, wo du das wie machen möchtest.

    ErfinderDesRades ist die Woche im Urlaub. Ich arbeite aber auch an vielen Stellen mit bs.FilterX, wir schaffen das bestimmt auch mal ohne ihn :P
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Also ich möchte meine Bindingsource filtern.
    Unter anderem hiernach:

    VB.NET-Quellcode

    1. Dim StartDate As Date = New Date(DTPStart.Value.Year, DTPStart.Value.Month, DTPStart.Value.Day, 0, 0, 0)
    2. Dim EndDate As Date = New Date(DTPEnd.Value.Year, DTPEnd.Value.Month, DTPEnd.Value.Day, 23, 59, 0)
    3. ArticleBindingSource.FilterX("LastCalculationSP >= ? And LastCalculationSP <= ?", StartDate, EndDate)

    Ich stelle mit zwei DTP ein Anfangs- und Enddatum ein.
    Dann werden mir nur Artikel angezeigt, bei denen sich in diesem Datumsbereich der Verkaufspreis geändert hat.
    Weil ich Probleme mit der Zeit im Datum hatte (und aus dem Grund nicht alles angezeigt wurde) habe ich die Zeiteinstellung in den beiden Variablen eingebaut.
    Bis hierhin geht alles.

    Das Problem ist jetzt, dass ich aus mehreren Filteroptionen (mittels Checkboxen) Einen searchstring zusammenbaue.
    Das macht die sub Buildsearchstring(append as boolean, searchtext as string).
    letzlich prüfe ich, ob die entsprechende Checkbox geklickt ist und füge dann den entsprechenden filtertext in meinem searchstring ein.
    (habe meinen Programmier PC nicht bei, Deswegen kein Beispiel)
    Also mein konretes Problem ist, dass
    buildsearchstring(true, "LastCalculationSP >= ? And LastCalculationSP <= ?", StartDate, EndDate)
    nicht funktioniert, weil Buildsearchstring mit Startdate und Enddate nichts anzufangen weiß.
    Damit ich die beiden Variablen nicht in meine Funktion einbauen muss (Damit ich sie in einem von 10 aufrufen übergeben kann), wollte ich die "?" In meinem Filterstring so ersetzen, dass ich es an meine Funktion übergeben kann.
    Aber ArticleBindingSource.FilterX($"LastCalculationSP >= {StartDate} And LastCalculationSP <= {EndDate}") führt mich in einen Fehler (post 1)

    Also kurz und knapp:
    aus dem hier

    VB.NET-Quellcode

    1. "LastCalculationSP >= ? And LastCalculationSP <= ?", StartDate, EndDate

    muss ein einzelner String ohne Wildcards ("?") werden, den ich an eine Funktion _searchstring = Functionname(Stringvariable as string) as string übergeben kann, Damit Bindingsource.filterx(_searchstring) funktioniert
    kurzer Einwurf:

    VB.NET-Quellcode

    1. Dim StartDate As Date = New Date(DTPStart.Value.Year, DTPStart.Value.Month, DTPStart.Value.Day, 0, 0, 0)
    2. Dim EndDate As Date = New Date(DTPEnd.Value.Year, DTPEnd.Value.Month, DTPEnd.Value.Day, 23, 59, 0)

    ->

    VB.NET-Quellcode

    1. Dim StartDate As Date = DTPStart.Value.Date
    2. Dim EndDate As Date = DTPEnd.Value.Date.AddDays(1).AddMinutes(-1)


    Die Frage, die Du Dir stellen musst, ist: welche Zeichenfolge wird als Vergleichswert akzeptiert? Wenn Du das weißt, kannst Du es aus dem echten Datum auch zusammenbauen. Du musst also ein Beispiel finden und am besten auch posten, bei dem eine fixe Zeichenfolge zum Erfolg führt. Keine Variable einbauen, sondern nur z.B. schreiben, dass (falls zutreffend) LastCalculationSP >= 03.06.2021 And LastCalculationSP <= 04.06.2021 zum Erfolg führt.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    DerSmurf schrieb:

    Das Problem ist jetzt, dass ich aus mehreren Filteroptionen (mittels Checkboxen) Einen searchstring zusammenbaue.

    hatten wir das nicht schonmal bei dir bei einem anderen Projekt?
    bs.FilterX wirst du da nicht nehmen können, sonder müsstest dann mit bs.Filter ohne X arbeiten - geht aber genauso gut, ist nur nicht so komfortabel.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    @tragl
    Wir hatten das ganze genau bei der Problematik hier. Da haben wir damals aus Filter, FilterX gemacht.
    Diese Suchfunktion soll jetzt um eine Funktion - eben die geänderten VK Preise mit Datumsauswahl der Änderung - erweitert werden.

    Hier der Erstellcode:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private _SearchString As String
    2. Private Sub CheckStateChanged(sender As Object, e As EventArgs) Handles CBSalesMargin.CheckStateChanged, CBRetailPrice.CheckStateChanged, CBPurchasingPrice.CheckStateChanged, CBNote.CheckStateChanged, CBName2.CheckStateChanged, CBName1.CheckStateChanged, CBListPrice.CheckStateChanged, CBEAN.CheckStateChanged, CBDiscount.CheckStateChanged, CBArtNo.CheckStateChanged, RBSearchExact.CheckedChanged, CBXExpiring.CheckedChanged
    3. BuildSearchString()
    4. End Sub
    5. 'Change Events der DateTimePicker
    6. Private Sub DTPStart_ValueChanged(sender As Object, e As EventArgs) Handles DTPStart.ValueChanged, DTPEnd.ValueChanged
    7. BuildSearchString()
    8. End Sub
    9. Private Sub BuildSearchString()
    10. 'Platzhalter für den Suchbegriff
    11. Dim Search = "xxooxx"
    12. 'Suchoperator
    13. Dim Asteriks = "*"
    14. If RBSearchExact.Checked Then Asteriks = ""
    15. 'Searchstring leeren, um uncheck abzufangen
    16. _SearchString = ""
    17. 'Artikelnummer
    18. If CBArtNo.Checked Then
    19. If _SearchString = "" Then
    20. EditSearchString(True, $"ArtNr LIKE '{Asteriks}{Search}{Asteriks}'")
    21. Else
    22. EditSearchString(False, $"OR ArtNr LIKE '{Asteriks}{Search}{Asteriks}'")
    23. End If
    24. End If
    25. 'EAN
    26. If CBEAN.Checked Then
    27. If _SearchString = "" Then
    28. EditSearchString(True, $"EAN LIKE '{Asteriks}{Search}{Asteriks}'")
    29. Else
    30. EditSearchString(False, $"OR EAN LIKE '{Asteriks}{Search}{Asteriks}'")
    31. End If
    32. End If
    33. 'Name1
    34. If CBName1.Checked Then
    35. If _SearchString = "" Then
    36. EditSearchString(True, $"Name1 LIKE '{Asteriks}{Search}{Asteriks}'")
    37. Else
    38. EditSearchString(False, $"OR Name1 LIKE '{Asteriks}{Search}{Asteriks}'")
    39. End If
    40. End If
    41. 'Name2
    42. If CBName2.Checked Then
    43. If _SearchString = "" Then
    44. EditSearchString(True, $"Name2 LIKE '{Asteriks}{Search}{Asteriks}'")
    45. Else
    46. EditSearchString(False, $"OR Name2 LIKE '{Asteriks}{Search}{Asteriks}'")
    47. End If
    48. End If
    49. 'Listenpreis
    50. If CBListPrice.Checked Then
    51. If _SearchString = "" Then
    52. EditSearchString(True, $"Convert(ListPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    53. Else
    54. EditSearchString(False, $"OR Convert(ListPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    55. End If
    56. End If
    57. 'Rabatt
    58. If CBDiscount.Checked Then
    59. If _SearchString = "" Then
    60. EditSearchString(True, $"Convert(Discount, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    61. Else
    62. EditSearchString(False, $"OR Convert(Discount, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    63. End If
    64. End If
    65. 'Einkaufpspreis
    66. If CBPurchasingPrice.Checked Then
    67. If _SearchString = "" Then
    68. EditSearchString(True, $"Convert(PurchasingPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    69. Else
    70. EditSearchString(False, $"OR Convert(PurchasingPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    71. End If
    72. End If
    73. 'Spanne
    74. If CBSalesMargin.Checked Then
    75. If _SearchString = "" Then
    76. EditSearchString(True, $"Convert(SalesMargin, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    77. Else
    78. EditSearchString(False, $"OR Convert(SalesMargin, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    79. End If
    80. End If
    81. 'Verkaufspreis
    82. If CBRetailPrice.Checked Then
    83. If _SearchString = "" Then
    84. EditSearchString(True, $"Convert(RetailPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    85. Else
    86. EditSearchString(False, $"OR Convert(RetailPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    87. End If
    88. End If
    89. 'Notiz
    90. If CBNote.Checked Then
    91. If _SearchString = "" Then
    92. EditSearchString(True, $"Convert(Note, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    93. Else
    94. EditSearchString(False, $"OR Convert(Note, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    95. End If
    96. End If
    97. 'ausgelaufen
    98. If CBXExpiring.Checked Then
    99. If _SearchString = "" Then
    100. EditSearchString(True, "Expiring = true")
    101. Else
    102. _SearchString = "(" & _SearchString & ") AND Expiring = true"
    103. End If
    104. End If
    105. ''geänderte Verkaufspreise
    106. 'If CBSPChange.Checked Then
    107. ' Dim StartDate As Date = DTPStart.Value.Date
    108. ' Dim EndDate As Date = DTPEnd.Value.Date.AddDays(1).AddMinutes(-1)
    109. ' If _SearchString = "" Then
    110. ' EditSearchString(True, $"LastCalculationSP >= {StartDate} And LastCalculationSP <= {EndDate}")
    111. ' Else
    112. ' EditSearchString(False, $"LastCalculationSP >= {StartDate} And LastCalculationSP <= {EndDate}")
    113. ' End If
    114. 'End If
    115. StartArticleSearch()

    Die Sub StartArticleSearch führt noch ein paar Prüfungen durch, und macht im Grunde das hier:

    VB.NET-Quellcode

    1. ArticleBindingSource.RemoveFilter()
    2. ArticleBindingSourceFiltered.RemoveFilter()
    3. Dim Search = TBSearchArticles.Text
    4. Dim Searchstring As String = Microsoft.VisualBasic.Replace(_SearchString, "xxooxx", Search)
    5. If CBShowAllArticle.Checked Then
    6. ArticleBindingSource.FilterX(Searchstring)
    7. Else
    8. ArticleBindingSourceFiltered.FilterX(Searchstring)
    9. End If

    Das ganze hängt an einem DGV zur Anzeige der Daten. Hier gibt es die Möglichkeit die Artikel nach Firmen zu sortieren.
    Daher die zwei verschiedenen BindingSources.


    @VaporiZed
    Ich hoffe ich habe dich richtig verstanden. Ich habe das ganze im Einzelschritt laufen lassen, mit einem Filterausdruck der funktioniert. Den Filterausdruck aus der FilterX Methode habe ich mir dann rauskopiert und als Code aufgerufen: ArticleBindingSource.FilterX("LastCalculationSP >= #06/04/2021 00:00:00# And LastCalculationSP <= #06/04/2021 23:59:00#")
    So funktioniert das ganze.
    Dann habe ich mir den Inhalt von StartDate und Enddate angeschaut.
    Diese sind: #6/4/2021 12:00:00 AM# (Start) und #6/4/2021 11:59:00 PM# (end).
    Da diese Variableninhalte identisch sind mit den Daten aus dem FilterX aufruf, habe ich diese wie folgt einbgebaut:
    ArticleBindingSource.FilterX("LastCalculationSP >= " & StartDate & " And LastCalculationSP <= " & EndDate)
    Wenn ich das ganze aber dann durchlaufen lasse, fehlen die "#". Der Filteraufruf der FilterX Methode sieht so aus:
    "LastCalculationSP >= 04.06.2021 And LastCalculationSP <= 04.06.2021 23:59:00"
    Das führt dann zum Fehler "Die Zeichenfolge wurde nicht als gültige DateTime erkannt. Ein unbekanntes Wort beginnt bei Index 11."g bei folgendem String:
    Also habe ich die fehlenden # in den String eingebaut:
    ArticleBindingSource.FilterX("LastCalculationSP >= #" & StartDate & "# And LastCalculationSP <= #" & EndDate & "#")
    Das sieht jetzt irgendwie bekackt aus, aber geht:

    VB.NET-Quellcode

    1. EditSearchString(True, "LastCalculationSP >= #" & StartDate & "# And LastCalculationSP <= #" & EndDate & "#")
    2. MessageBox.Show(_SearchString)

    liefert mir einen korrekten Searchstring.

    Ich baus mal ein.

    Edit: @VaporiZed Du bist mein Held. Es läuft!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DerSmurf“ ()

    DerSmurf schrieb:

    EditSearchString(True, "LastCalculationSP >= #" & StartDate & "# And LastCalculationSP <= #" & EndDate & "#")

    und schicker dann so: EditSearchString(True, $"LastCalculationSP >= #{StartDate}# AND LastCalculationSP <= #{EndDate}#")
    ;)
    Funktioniert anders im Übrigen nicht, weil die FilterX-Methode alles in String umwandelt. Könntest da was machen mit "WHERE Convert(System.String)Datum..." - das hatt ich auch an 1-2 Stellen mal, weil's anders nicht ging - müsste auch in dem früheren Projekt von dir mit drin sein.
    Aber ich glaub' in dem Fall könnte man sich nur die # sparen, dafür haste dann längeren Text/Code, was ja auch unsinnig wäre
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup: