BindingSource.Filter mit unterschiedlichen Datentypen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 38 Antworten in diesem Thema. Der letzte Beitrag () ist von DerSmurf.

    BindingSource.Filter mit unterschiedlichen Datentypen

    Hallo ihr lieben
    Ich habe eine Bindingsource, die ich mithilfe einer Textbox filtere und so quasi eine Volltextsuche habe.
    Bisher habe ich immer nur String Datentypen durchsucht, das sah wie folgt aus:

    VB.NET-Quellcode

    1. Dim Search = TBSearchArticles.Text
    2. ArticleBindingSource.Filter = "ArtNr like '%" & Search & "%' OR Name1 like '%" & Search & "%' OR EAN like '%" & Search & "%'"

    Klappt wunderbar.
    Jetzt möchte ich auswählbar machen, welche Spalten durchsucht werden und es sollen neue durchsuchbare Spalten hinzukommen.
    So versuche ich gerade testweise die Spalte ListPrice (Double) in die bestehende Suche zu integrieren.
    Folgender Code klappt:

    VB.NET-Quellcode

    1. ArticleBindingSource.Filter = "ArtNr like '%" & Search & "%' OR Name1 like '%" & Search & "%' OR EAN like '%" & Search & "%' OR ListPrice = " & CDbl(Search)

    aber wenn ich "1,5" eingebe, bekomme ich folgende Fehlermeldung:
    ​System.Data.SyntaxErrorException: "Syntaxfehler im Ausdruck."
    Da ist wohl ein Syntaxfehler im Ausdruck.
    Dann guck dir den Ausdruck mal an - oder poste ihn.
    Bisher ist ja nur zu sehen, wie der Ausdruck gebildet wird - nicht: was dabei herauskommt.

    Im Moment des Auftretens des Fehlers - Was kommt dann dabei raus:

    VB.NET-Quellcode

    1. "ArtNr like '%" & Search & "%' OR Name1 like '%" & Search & "%' OR EAN like '%" & Search & "%' OR ListPrice = " & CDbl(Search)
    Das ist die Frage.
    ja, genau.
    Jo - und der Fehler ist wohl, dass ListPrice in invariantCulture formatiert sein muss, also muss 1.5 sein statt 1,5.



    Du könntest meine Filter-Extension in Betracht ziehen - gugge DataExpressions: Filter und berechnete Spalten im Dataset .
    Weil es gibt bei DataExpressions noch mehr so kultur-abhängige Fussangeln.
    Deine Filterung würde ausserdem glaub auch leserlicher:

    VB.NET-Quellcode

    1. ArticleBindingSource.FilterX("ArtNr like %?% OR Name1 like %?% OR EAN like %?% OR ListPrice = ?", search, search, search, CDbl(search))

    Aber bereits einfache Verwendung der String-Interpolation würde die Leserlichkeit erheblich verbessern, und könnte ebenfalls das Kultur-Problem lösen.
    Der & - Operator erzeugt doch grauenhaft unleserliche String-Häcksel - ich verwende den überhaupt nie mehr.

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

    außerdem wirst du alles in String umwandeln müssen (wie hier am Beispiel, da suche ich nach Integer):
    bsTour.FilterX("Convert(TourNr, System.String) LIKE *?*", tbSuche.Text)
    Das muss zumindest dann gemacht werden, wenn du den LIKE-Operator verwenden willst.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Hallo @tragl danke für den Einwand. Sehr hilfreich :o)
    Aber ich bin zu doof irgendwie.

    Der Code vom @ErfinderDesRades funktioniert nicht. So sieht meine Sub jetzt aus:

    VB.NET-Quellcode

    1. Private Sub TBSearchArticles_TextChanged(sender As Object, e As EventArgs) Handles TBSearchArticles.TextChanged
    2. Dim Search = TBSearchArticles.Text
    3. 'ArticleBindingSource.FilterX("ArtNr like %?% OR Name1 like %?% OR EAN like %?% OR Convert(ListPrice, System.String) LIKE *?*", Search, Search, Search, Search)
    4. ArticleBindingSource.FilterX("ArtNr like %?%", Search)
    5. 'ArticleBindingSource.FilterX("Convert(ListPrice, System.String) LIKE *?*", Search) 'FUNKTIONIERT
    6. 'ArticleBindingSource.FilterX("ArtNr like %?% OR Name1 like %?% OR EAN like %?% OR ListPrice = ?", Search, Search, Search, CDbl(Search))
    7. End Sub

    die einzige funktionierende Zeile ist Zeile 5. Diese tut was sie soll. Bei allen anderen tritt der gleiche Fehler auf.
    Ich teste jetzt mal mit einkommentierter Zeile 4 - das ist der kürzeste Code:
    Der Fehler tritt immer auf, egal was eingegeben wird: System.Data.SyntaxErrorException: "Syntaxfehler: Fehlender Operand vor dem Operator 'Mod'."
    in dieser Sub: Public Sub FilterX(bs As BindingSource, expression As String, ParamArray values() As Object)
    Der Filterstring lautet: "ArtNr like %'5'%"
    Der Filterstring an sich sieht für mich gut aus. Was habe ich falsch gemacht?
    Hast du mal % durch * ersetzt? Ich kenne nur * für LIKE-Operationen
    Also ArticleBindingSource.FilterX("ArtNr LIKE *?*", Search)

    Ansonsten war mit String-Interpolation das hier gemeint (so sähe deine Zeile ohne die FilterX-Expression aus):
    ArticleBindingsource.Filter = $"ArtNr LIKE '*{Search}*' OR Name1 LIKE '*{Search}*' OR EAN LIKE '*{Search}*' OR Convert(ListPrice, System.String) = {Search}"

    Ich find die Extension aber besser weil da kannst du dann auch die ' weglassen, die hat man schnell ma vergessen. Vielleicht kann @ErfinderDesRades ja seine Methode
    noch mit Convert(xx, System.String) ergänzen, falls man mit LIKE operiert.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

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

    Ah mist.
    Der Unterschied hätte mir auffallen können In deinem Code ist ja das Sternchen vorhanden und der läuft. (Zeile 5)
    Nunja - du hast Recht.
    ArticleBindingSource.FilterX("ArtNr like *?* OR Name1 like *?* OR EAN like *?* OR Convert(ListPrice, System.String) LIKE *?*", Search, Search, Search, Search)
    sucht ohne murren.

    gutgut, dann mache ich mich jetzt mal ran mir einen Suchstring zusammenzufrickeln, je nachdem welche Checkboxen - mit DataTable Spalten - der User anklickt.

    Ich danke euch beiden!
    Ich mach sowas gerne mit RadioButtons - den meiner Meinung nach am häufigst verwendeten im Designer auf Checked = True stellen
    und dann im Code mit einem Select Case arbeiten - ein User wird in den seltensten Fällen alle Felder durchsuchen wollen / müssen.



    VB.NET-Quellcode

    1. Private Sub suche()
    2. If Not tbSuche.Text = "" Then
    3. Select Case True
    4. Case rbtnTourname.Checked : bsTour.FilterX("Tourname LIKE *?*", tbSuche.Text) : bsTour.msgDGVnoEntry : dgv.Select()
    5. Case rbtnTournummer.Checked : bsTour.FilterX("Convert(TourNr, System.String) LIKE *?*", tbSuche.Text) : bsTour.msgDGVnoEntry : dgv.Select()
    6. End Select
    7. Else
    8. bsTour.Filter = ""
    9. End If
    10. End Sub


    und falls das Suchfeld leer ist, wieder alle Einträge anzeigen. (Zeile 8)
    Bindingsource.msgDGVnoEntry ist eine kleine Extension die eine Messagebox auswirft, wenn keine Einträge vorhanden sind:

    VB.NET-Quellcode

    1. ''' <summary>zeigt eine Messagebox, wenn die gefilterte Bindingsource keine Elemente enthält</summary>
    2. <Extension>
    3. Public Sub msgDGVnoEntry(bs As BindingSource)
    4. If bs.Count = 0 Then msgInformation("keine Einträge")
    5. End Sub
    6. Public Sub msgInformation(Nachricht As String)
    7. MessageBox.Show(Nachricht, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
    8. End Sub
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Huhu
    Ich habe auch schon an Radiobuttons gedacht.
    Aber tatsächlich reicht es mir nicht aus, wenn ich nur eine - oder alle - Spalten durchsuchen kann.
    Aktuell habe ich ja nur eine "komplett" Suche, wo die Suchspalten im Code festgelegt sind.
    Hier stört mich konkret bei manueller Rechnungskontrolle, dass mir permanent Artikel angezeigt werden, die eine gesuchte Artikelnummer im Namen, oder im EAN Code haben.
    Auch stört mich, dass ich nur mit dem Operator "Like" suchen kann, nicht mit "=".
    Aber es passiert, dass ich Werte in mehreren Spalten suchen möchte.
    Also leider keine Radiobuttons.

    Meine Überlegung waren eben checkboxen für die zu durchsuchenden Spalten und 2 Radiobuttons für die Operatoren "like" und "=".
    Dann deklariere ich eine globale Searchstring Variable und abboniere die checkstate_Changed Events der Checkboxen mit folgender Sub:

    VB.NET-Quellcode

    1. Private _Searchstring as string
    2. Private Sub BuildSearchstring
    3. 'Zustand von Radio Button prüfen, ob mit Operator Like, oder = gesucht wird.
    4. 'nacheinander alle Checkboxen auf Zustand prüfen
    5. 'wenn checked, dann prüfen ob _Searchstring = "" - und _Searchstring entsprechend füllen (neu oder anhängen)
    6. End sub

    Im Textchange Event der Suchen Textbox wird dann der Suchbegriff aus der Textbox in den _Searchstring geschrieben und nach diesem gefiltert.

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

    Also für die Komplettsuche könntest du einen RadioButton "rbtnVolltext" bauen.
    Ansonsten geh' mal davon aus dass die User gerne Tippfehler machen, weshalb eine LIKE-Suche eigentlich unabdingbar ist.

    Wenn du aber unbedingt die beiden Varianten willst dann mach doch mehrere Radiobuttons
    so würde ich das für mich lösen. Und dann verschachtelte Select Case-Abfrage (kann sein dass das noch eleganter geht aber da bin
    ich noch nicht fit genug für :P )

    Suchbegriff
    Suchschlüssel
    Genauigkeit
    Textbox
    Radiobutton(s) für Suchspalten
    Radiobutton "Exakte Übereinstimmug" (=-Suche)
    Button
    Radiobutton für Volltextsuche (alle Spalten)
    Radiobutton "ungefähre Übereinstimmung" (Like-Suche)

    Bei Checkboxen haste die Gefahr dass der User dann auch beides will - und wie willst du das abfangen? Sind 2 Checkboxen vorhanden hast du schonma folgende Möglichkeiten
    und das erweitert sich in's Unübersichtliche je mehr Checkboxen du verwendest.

    - keine Checkbox
    - 1 Checkbox
    - beide Checkboxen

    EDIT: Wenn du dir den Suchstring doch zusammenhäkeln lassen willst dann wäre das hier vielleicht ein Ansatz.
    Das Teil arbeitet damit - ist aber komplex.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Hmm. Ich habe mir das ganz einfach gedacht. Aber klappt glaube ich nicht.
    Hier mal meine Gedanken, ausprogrammiert, mit 2 Checkboxen:

    VB.NET-Quellcode

    1. Private _Searchstring as string
    2. Private Sub CBArtNo_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
    3. BuildSearchString
    4. End Sub
    5. Private Sub BuildSearchString()
    6. 'das Problem
    7. Dim Search As String = ""
    8. 'Searchstring leeren, um uncheck abzufangen
    9. _SearchString = ""
    10. 'Artikelnummer
    11. If CBArtNo.Checked Then
    12. If _SearchString = "" Then
    13. EditSearchString(True, """ArtNr like '%" & Search & "%'""")
    14. Else
    15. EditSearchString(False, """OR ArtNr like '%" & Search & "%'""")
    16. End If
    17. End If
    18. 'EAN
    19. If CBEAN.Checked Then
    20. If _SearchString = "" Then
    21. EditSearchString(True, """EAN like '%" & Search & "%'""")
    22. Else
    23. EditSearchString(False, """OR EAN like '%" & Search & "%'""")
    24. End If
    25. End If
    26. End Sub
    27. Private Sub EditSearchString(StringEmpty As Boolean, Searchtext As String)
    28. If StringEmpty Then
    29. _SearchString = Searchtext
    30. Else
    31. _SearchString &= Searchtext
    32. End If
    33. End Sub
    34. Private Sub TBSearchArticles_TextChanged(sender As Object, e As EventArgs) Handles TBSearchArticles.TextChanged
    35. 'in der Sub soll nun "Search" - im _Searchstring gefüllt werden
    36. End Sub


    Der Searchstring sieht gut aus, aber es fehlt natürlich der Inhalt aus Search. Kann ich diesen im Text Changed Event der Suchen Textbox nachträglich füllen (Stringinterpolation), oder geht das nicht und mein gesamter Ansatz ist Mist?
    Wenn das so nicht klappt, müsste ich ja alle abfragen (erstmal die 10 Checkboxen), später dann noch 2 Radiobuttons für like und = Suche - durch das TextChange Event aufrufen - dann habe ich Sorge, dass es zu Verzögerungen bei der Suche kommt.

    Edit:
    Ich könnte die Search Variable in der BuildSearchString ja mit einem Platzhalter füllen und im TexdtChanged Event mit replace durch den Inhalt der Textbox füllen.
    Das müsste doch funktionieren.

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

    DerSmurf schrieb:

    dann habe ich Sorge, dass es zu Verzögerungen bei der Suche kommt.

    das bezweifel' ich

    Du arbeitest aber schon wieder mit % anstatt * - da kann das Problem schon sein.
    Ansonsten sowas machen wie

    VB.NET-Quellcode

    1. If _SearchString = "" Then
    2. _SearchString = $"{suchtext}"
    3. Else
    4. _SearchString = $"{_SearchString} AND/OR/LIKE {suchtext}"
    5. End If


    Du kannst die String's quasi addieren - musst dich aber entscheiden mit welchem Operator du arbeiten willst.
    Und was machst du in deinem Beispiel wenn beide CheckBoxen checked sind oder gar keine? Soweit ich das sehe hast du 10 Checkboxes... das bedeutet so oder so ne Menge arbeit.
    Daher der Vorschlag mit den Radiobuttons: mach einen als "Volltextsuche" wo du alle Spalten reinnimmsst, ansonsten lass' die Leute die Spalte
    selektieren in der sie suchen wollen. Wenn ich eine Artikelnummer suche, dann brauch er nicht in einer Bezeichnung oder EAN oder im Preis zu suchen - da reicht mir die Artikelnummer-Spalte. ;)

    Oder.. andere Idee - du häkelst dir was zusammen, wie es bei uns im WaWi vorkommt:

    Du bastelst dir in der Form den Filter zusammen. Wählst eine Spalte aus einem Dropdown aus, klickst an ob Text/Text ungefähr etc. und speicherst.
    Willst du weitere Filter dann musste dich entscheiden ob UND/ODER und wieder die gleiche Auswahl. Müsste man mal testen aber wäre vermutlich
    zu mächtig bei dem was du vor hast.



    Das wird bei uns genutzt, um Gesamtlisten einer Tabelle (Konzern = jede jede jede Menge Daten) übersichtlich wegzufiltern und im Anschluss nach Excel zu exportieren..
    Für die "normalen Suchen" haben wir sowas, was ich dir bereits vorschlug:

    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Ich verstehe nicht wo das Problem der 10 Checkboxen ist.
    Für 2 habe ich doch den Code fertig.
    Es ist jeweils eine verschachtelte If Anfrage, mit immer der gleichen sind die aufgerufen wird.
    Es gibt bei mir mehrere Szenarien, in der ich nach mehr als einer Spalte suche - aber nicht in allen
    Musst du für dich selbst entscheiden, ob das ein Problem wird - hast du denn mal probiert, ob das Ersetzen von % durch * dein Problem löst?
    Außerdem hab ich grad gesehen, dass du mit Zeile 8 dein Search leerst. Sollte da nicht was stehen wie Search = tbSuche.Text oder so?
    Und versuch' mal mit StringInterpolation zu arbeiten.
    Aus
    EditSearchString(False, """OR EAN like '%" & Search & "%'""")
    wird
    EditSearchString(False, $"OR EAN LIKE '*{Search}*'"

    das liest sich bei langen Strings wesentlich schöner und du kannst direkt erkennen, wo du Variable in den String gepackt hast.
    Hier mal leserlich:
    Spoiler anzeigen

    Visual Basic-Quellcode

    1. Private _Searchstring As String = "" 'Searchstring leeren, um uncheck abzufangen?
    2. Private Sub cb_CheckStateChanged(sender As Object, e As EventArgs) Handles cbSalesMargin.CheckStateChanged,
    3. cbRetailPrice.CheckStateChanged,
    4. cbPurchasingPrice.CheckStateChanged,
    5. cbNote.CheckStateChanged,
    6. cbName2.CheckStateChanged,
    7. cbName1.CheckStateChanged,
    8. cbListPrice.CheckStateChanged,
    9. cbEAN.CheckStateChanged,
    10. cbDiscount.CheckStateChanged,
    11. cbArtNo.CheckStateChanged
    12. BuildSearchString()
    13. End Sub
    14. Private Sub BuildSearchString()
    15. Dim Search As String = tbSuche.Text
    16. Select Case True
    17. 'Artikelnummer
    18. Case cbArtNo.Checked
    19. If _SearchString = "" Then
    20. EditSearchString(True, $"ArtNr LIKE '*{Search}*'")
    21. Else
    22. EditSearchString(False, $"OR ArtNr LIKE '*{Search}*'")
    23. End If
    24. 'EAN
    25. Case cbEAN.Checked
    26. If _SearchString = "" Then
    27. EditSearchString(True, $"EAN LIKE '*{Search}'")
    28. Else
    29. EditSearchString(False, $"OR EAN LIKE '*{Search}*'")
    30. End If
    31. End Select
    32. End Sub
    33. Private Sub EditSearchString(StringEmpty As Boolean, Searchtext As String)
    34. If StringEmpty Then
    35. _SearchString = $"{Searchtext}"
    36. Else
    37. _SearchString = $"{_SearchString}{Searchtext}"
    38. End If
    39. End Sub
    40. Private Sub TBSearchArticles_TextChanged(sender As Object, e As EventArgs) Handles TBSearchArticles.TextChanged
    41. 'in der Sub soll nun "Search" - im _Searchstring gefüllt werden
    42. End Sub


    So könnt's auch gehen (noch viel kürzer):
    Spoiler anzeigen

    Visual Basic-Quellcode

    1. Private _Searchstring As String = "" 'Searchstring leeren, um uncheck abzufangen?
    2. Private _Search As String = ""
    3. Private Sub cb_CheckStateChanged(sender As Object, e As EventArgs) Handles cbSalesMargin.CheckStateChanged,
    4. cbRetailPrice.CheckStateChanged,
    5. cbPurchasingPrice.CheckStateChanged,
    6. cbNote.CheckStateChanged,
    7. cbName2.CheckStateChanged,
    8. cbName1.CheckStateChanged,
    9. cbListPrice.CheckStateChanged,
    10. cbEAN.CheckStateChanged,
    11. cbDiscount.CheckStateChanged,
    12. cbArtNo.CheckStateChanged
    13. BuildSearchString()
    14. End Sub
    15. Private Sub BuildSearchString()
    16. _Search = tbSuche.Text
    17. Select Case True
    18. 'Artikelnummer
    19. Case cbArtNo.Checked : EditSearchString(OR_LIKE("ArtNr"))
    20. 'EAN
    21. Case cbEAN.Checked : EditSearchString(OR_LIKE("EAN"))
    22. End Select
    23. End Sub
    24. Private Sub EditSearchString(Searchtext As String)
    25. If _SearchString = "" Then
    26. _SearchString = $"{Searchtext}"
    27. Else
    28. _SearchString = $"{_SearchString}{Searchtext}"
    29. End If
    30. End Sub
    31. ''' <Summary> Erzeugt eine Filter-Expression mit den Operatoren OR LIKE </summary> '''
    32. Private Function OR_LIKE(Spalte As String) As String
    33. If _SearchString = "" Then
    34. Return $"{Spalte} LIKE '*{_Search}*'"
    35. Else
    36. Return $"OR {Spalte} LIKE '*{_Search}*'"
    37. End If
    38. End Sub
    39. Private Sub TBSearchArticles_TextChanged(sender As Object, e As EventArgs) Handles TBSearchArticles.TextChanged
    40. 'in der Sub soll nun "Search" - im _Searchstring gefüllt werden
    41. End Sub

    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „tragl“ ()

    Alles klar.
    Ja, das * löst mein Problem.
    Ich schreibe den Code heute mal zuende und schmeiß den hier rein.

    Edit:
    Der eigentliche Suchbegriff kommt ja erst im Text Change Event in den _Searchstring.
    Der _Searchstring an sich, wird ja aber vorher erstellt.

    VB.NET-Quellcode

    1. 'Searchstring leeren, um uncheck abzufangen
    2. _SearchString = ""

    Diese Zeile führe ich aus, weil sich der _Searchstring ja sonst nicht ändert, wenn ich eine Checkbox unchecke.

    DerSmurf schrieb:

    Diese Zeile führe ich aus, weil sich der _Searchstring ja sonst nicht ändert, wenn ich eine Checkbox unchecke.

    du leerst den aber jedesmal wenn du ne checkbox anklickst - liest sich so, als ginge das an der useabilty vorbei..
    So wie sich das anhört soll die Suche schon beim Eingeben losgehen - aber was ist wenn der User die Checkbox noch nicht angehakt hat sondern erst den Suchbegriff eingibt?
    Den darf er nach dem Anhaken wieder neu eingeben bzw. zumindest muss er ihn verändern damit die Suche wieder losgeht. Wär' das über einen Such-Button nicht eleganter, wo die
    Suche erst ausgelöst wird wenn der User fertig ist mit seinen Eingaben?

    Und was ist dann Dim Search As String = ""?

    Hast du deine Daten in einem DataSet? Kannst auch gerne mal das Projekt anhängen...
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:
    Huhu
    Das Projekt hänge ich nicht an, weils ein Risending ist - mit jede menge Code.
    Wenn ich das hier ranschmeiße, wirst du nicht mehr fertig mit meinen Code anschauen und wir kommen vom eigentlichen Problem weg :o)
    Ich bastel die aber sehr. sehr gerne ein DemoProjekt, wenn du magst (und brauchst).
    Das mache ich normalerweise immer so, damit es eben uploadbar ist. Aber da das hier vergleichsweise wenig Code ist, und das erstellen einer DemoSolution (mit DataSet und Gedöns), vergleichsweise aufwendig ist, hab ichs mir gespart. Mache ich wie gesagt aber sehr, sehr gerne, wenns dir hilft.

    Ich habe mal ein Bild des Programmes angehängt, damit du die UserEingabe siehst. Der untere Teil mit DGV ist mit einem Split Container geteilt. Die Sucheingabe befindet sich im Panel2. Dieses ist standartmäßig ausgeblendet (collapsed = True) und wird mit dem Button mit Zahnrad (wo der Cursor drauf ist) ein- und ausgeblendet.
    Das Suchfeld ist die Textbox inner Mitte.

    Hier der Code:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class FrmMainForm
    2. Private _SearchString As String
    3. 'Check Event der Checkboxen und EINES Radiobuttons
    4. 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
    5. BuildSearchString()
    6. End Sub
    7. 'Sub zum erstellen des Suchstrings
    8. Private Sub BuildSearchString()
    9. 'Platzhalter für den Suchbegriff
    10. Dim Search = "xxooxx"
    11. 'Suchoperator
    12. Dim Asteriks = "*"
    13. If RBSearchExact.Checked Then Asteriks = ""
    14. 'Searchstring leeren, um uncheck abzufangen
    15. _SearchString = ""
    16. 'Artikelnummer
    17. If CBArtNo.Checked Then
    18. If _SearchString = "" Then
    19. EditSearchString(True, $"ArtNr LIKE '{Asteriks}{Search}{Asteriks}'")
    20. Else
    21. EditSearchString(False, $"OR ArtNr LIKE '{Asteriks}{Search}{Asteriks}'")
    22. End If
    23. End If
    24. 'EAN
    25. If CBEAN.Checked Then
    26. If _SearchString = "" Then
    27. EditSearchString(True, $"EAN LIKE '{Asteriks}{Search}{Asteriks}'")
    28. Else
    29. EditSearchString(False, $"OR EAN LIKE '{Asteriks}{Search}{Asteriks}'")
    30. End If
    31. End If
    32. 'Name1
    33. If CBName1.Checked Then
    34. If _SearchString = "" Then
    35. EditSearchString(True, $"Name1 LIKE '{Asteriks}{Search}{Asteriks}'")
    36. Else
    37. EditSearchString(False, $"OR Name1 LIKE '{Asteriks}{Search}{Asteriks}'")
    38. End If
    39. End If
    40. 'Name2
    41. If CBName2.Checked Then
    42. If _SearchString = "" Then
    43. EditSearchString(True, $"Name2 LIKE '{Asteriks}{Search}{Asteriks}'")
    44. Else
    45. EditSearchString(False, $"OR Name2 LIKE '{Asteriks}{Search}{Asteriks}'")
    46. End If
    47. End If
    48. 'Listenpreis
    49. If CBListPrice.Checked Then
    50. If _SearchString = "" Then
    51. EditSearchString(True, $"Convert(ListPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    52. Else
    53. EditSearchString(False, $"OR Convert(ListPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    54. End If
    55. End If
    56. 'Rabatt
    57. If CBDiscount.Checked Then
    58. If _SearchString = "" Then
    59. EditSearchString(True, $"Convert(Discount, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    60. Else
    61. EditSearchString(False, $"OR Convert(Discount, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    62. End If
    63. End If
    64. 'Einkaufpspreis
    65. If CBPurchasingPrice.Checked Then
    66. If _SearchString = "" Then
    67. EditSearchString(True, $"Convert(PurchasingPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    68. Else
    69. EditSearchString(False, $"OR Convert(PurchasingPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    70. End If
    71. End If
    72. 'Spanne
    73. If CBSalesMargin.Checked Then
    74. If _SearchString = "" Then
    75. EditSearchString(True, $"Convert(SalesMargin, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    76. Else
    77. EditSearchString(False, $"OR Convert(SalesMargin, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    78. End If
    79. End If
    80. 'Verkaufspreis
    81. If CBRetailPrice.Checked Then
    82. If _SearchString = "" Then
    83. EditSearchString(True, $"Convert(RetailPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    84. Else
    85. EditSearchString(False, $"OR Convert(RetailPrice, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    86. End If
    87. End If
    88. 'Notiz
    89. If CBNote.Checked Then
    90. If _SearchString = "" Then
    91. EditSearchString(True, $"Convert(Note, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    92. Else
    93. EditSearchString(False, $"OR Convert(Note, System.String) LIKE '{Asteriks}{Search}{Asteriks}'")
    94. End If
    95. End If
    96. StartArticleSearch()
    97. End Sub
    98. Private Sub EditSearchString(StringEmpty As Boolean, Searchtext As String)
    99. If StringEmpty Then
    100. _SearchString = $"{Searchtext}"
    101. Else
    102. _SearchString = $"{_SearchString}{Searchtext}"
    103. End If
    104. End Sub
    105. 'Sub zum starten der Artikelsuche
    106. Private Sub StartArticleSearch()
    107. If TBSearchArticles.Text = "" Then Exit Sub
    108. Dim Search = TBSearchArticles.Text
    109. Dim Searchstring As String = Microsoft.VisualBasic.Replace(_SearchString, "xxooxx", Search)
    110. ArticleBindingSource.FilterX(Searchstring)
    111. End Sub
    112. 'TextChange Event der Suchen Textbox
    113. Private Sub TBSearchArticles_TextChanged(sender As Object, e As EventArgs) Handles TBSearchArticles.TextChanged
    114. StartArticleSearch
    115. End Sub


    Wie gesagt - wenn das zuviel ist bastel ich dir sehr gerne ne Demo.

    Also der Code funktioniert einwandfrei. Was evtl. ein bsischen doof ist ist das Replace.
    Also wegen des Replace (gibts da echt keien VB Alternative), und wegen der Logik dahinert, dass ich in der Sub den Suchbegriff durch ersetzen einfüge.
    Evtl. sollte ich mir das ganze check Event Gedöns sparen und die komplette Suchlogik ins Change Event der Textbox klatschen.
    Also den Suchstring nicht vorab zusammenbauen, sondern erst wenn gesucht wird (Text Change).
    Hier wie gesagt ist aber meine Sorge, dass das die Suche verlangsamt. Denn eine Volltextsuche durch Name1 und Name2 von 20.000 Artikeln ist ja eh nicht das schnellste.
    Müsste ich mal Zeitmessungen machen.

    Zu deinen Anmerkungen:

    tragl schrieb:

    Wär' das über einen Such-Button nicht eleganter, wo die
    Suche erst ausgelöst wird wenn der User fertig ist mit seinen Eingaben?

    Ein Suchbutton würde viele meiner Probleme vereinfachern. Aber ich möchte unbedingt!, dass gesucht wird, ohne dass ich auf einen Button klicken muss.
    Die Suche erfolgt also im TextchangeEvent der Textbox, welche den Suchbegriff enthält.
    Es passiert, dass ich längere Rechnungen (100 Artikel+) manuell kontrollieren muss. Dann ist die Rechnung links auf dem Screen, das Programm rechts.
    Tastenanschläge werden direkt im KeyDown in die Textbox übertragen, dass ich einfach schreiben kann, ohne der Box den Fokus zu geben. Esc löscht die Suche.
    So kann ich dann wunderbar eine Artikelnummer nach der anderen in den PC Hämmern und mit Esc löschen. Das geht recht zügig.
    Ein permanenter Suchen Button Klick (oder Tastendruck), würde mich wirklich enorm stören.

    tragl schrieb:

    du leerst den aber jedesmal wenn du ne checkbox anklickst - liest sich so, als ginge das an der useabilty vorbei..

    Ich leere ja nur den Suchstring zu beginn der Sub und schreibe einen neuen. Die aktuelle Usersuche bleibt davon ja erstmal unberührt.
    Ich dachte mir einfach den String leeren und einen neuen schreiben ist einfacher. Denn im Beispiel der Art.Nr., müsste ich ja im Falle von "unchecked" prüfen, ob sie im _Searchstring vorkommt und rauslöschen.
    Das ist ja mega Aufwand im Vergleich zu meiner Lösung.

    tragl schrieb:

    So wie sich das anhört soll die Suche schon beim Eingeben losgehen - aber was ist wenn der User die Checkbox noch nicht angehakt hat sondern erst den Suchbegriff eingibt?

    Es sind per default die Checkboxen Art.Nr., EAN, und Name1 angehakt, sowie der Radiobutton "ungefähr". Danach wird also gesucht, wenn der User an den Sucheinstellungen nichts ändert.
    Wenn bei beschriebener Textbox die Checkboxen geändert werden, wird die Filterung neu angestoßen.

    tragl schrieb:

    Und was ist dann Dim Search As String = ""?

    Dies habe ich jetzt ersetzt durch ​ Dim Search = "xxooxx"
    Das ist der Platzhalter für den eigentlichen Suchbegriff.
    Da ich für gewöhnlich vor Eingabe des Suchbegriffes, an den Buttons rumklicke, wird der Suchstring erstellt, ohne das es etwas zu suchen gibt.
    In der eigentlichen Suchen Sub ​StartArticleSearch wird das "xxoxx" dann durch den Suchbegriff ersetzt, damit der Suchbegriff im Searchstring landet.
    Bilder
    • Unbenannt.jpg

      417,26 kB, 1.920×1.080, 55 mal angesehen

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

    DerSmurf schrieb:

    wenns dir hilft.

    das muss MIR nicht helfen, sondern dir :P aber wir versuchen's erstma so.

    Hast du ma probiert ob das Ganze noch funzt wenn du "exakt" angeklickt hast?
    Glaube nämlich nicht, weil LIKE ohne * eigentlich nix anfangen kann.

    Und dann gibt's noch ein Problem mit Zeile 110: FilterX brauch noch den / die Parameter. Hier kannst du dann eher mit Filter = arbeiten.

    Ich hab das ganze ma verschönert (hatte ich in meinem Post mit den 2 Spoilern aber eigentlich schonma gemacht) weil du immer die gleiche Methode verwendest, das geht schicker:
    Spoiler anzeigen

    Visual Basic-Quellcode

    1. Public Class FrmMainForm
    2. Private _SearchString As String
    3. Private _Search As String = "xxooxx"
    4. 'Check Event der Checkboxen und EINES Radiobuttons
    5. Private Sub CheckStateChanged(sender As Object, e As EventArgs) Handles CBSalesMargin.CheckStateChanged,
    6. CBRetailPrice.CheckStateChanged,
    7. CBPurchasingPrice.CheckStateChanged,
    8. CBNote.CheckStateChanged,
    9. CBName2.CheckStateChanged,
    10. CBName1.CheckStateChanged,
    11. CBListPrice.CheckStateChanged,
    12. CBEAN.CheckStateChanged,
    13. CBDiscount.CheckStateChanged,
    14. CBArtNo.CheckStateChanged,
    15. RBSearchExact.CheckedChanged
    16. BuildSearchString()
    17. End Sub
    18. 'Sub zum erstellen des Suchstrings
    19. Private Sub BuildSearchString()
    20. 'Searchstring leeren, um uncheck abzufangen
    21. _SearchString = ""
    22. Select Case True
    23. Case CBArtNo.Checked : EditSearchString(FilterExpression_OR("ArtNr"))
    24. Case CBEAN.Checked : EditSearchString(FilterExpression_OR("EAN"))
    25. Case CBName1.Checked : EditSearchString(FilterExpression_OR("Name1"))
    26. Case CBName2.Checked : EditSearchString(FilterExpression_OR("Name2"))
    27. Case CBListPrice.Checked : EditSearchString(FilterExpression_OR("ListPrice"))
    28. Case CBDiscount.Checked : EditSearchString(FilterExpression_OR("Discount"))
    29. Case CBPurchasingPrice.Checked : EditSearchString(FilterExpression_OR("PurchasingPrice"))
    30. Case CBSalesMargin.Checked : EditSearchString(FilterExpression_OR("SalesMargin"))
    31. Case CBRetailPrice.Checked : EditSearchString(FilterExpression_OR("RetailPrice"))
    32. Case CBNote.Checked : EditSearchString(FilterExpression_OR("Note"))
    33. End Select
    34. StartArticleSearch()
    35. End Sub
    36. Private Sub EditSearchString(Searchtext As String)
    37. If _SearchString = "" Then
    38. _SearchString = $"{Searchtext}"
    39. Else
    40. _SearchString = $"{_SearchString}{Searchtext}"
    41. End If
    42. End Sub
    43. ''' <summary> Erzeugt eine Filter-Expression mit dem Operator "OR" und falls ungefähre Suche, dann auch mit "LIKE". </summary> '''
    44. Private Function FilterExpression_OR(Spalte As String) As String
    45. If RBSearchExact.Checked Then 'exakte Suche ohne LIKE
    46. If _SearchString = "" Then
    47. Return $"{Spalte} = '{_Search}'"
    48. Else
    49. Return $"OR {Spalte} = '{_Search}'"
    50. End If
    51. Else 'ungefähre Suche mit LIKE
    52. If _SearchString = "" Then
    53. Return $"Convert({Spalte}, System.String) LIKE '*{_Search}*'"
    54. Else
    55. Return $"OR Convert({Spalte}, System.String) LIKE '*{_Search}*'"
    56. End If
    57. End If
    58. End Sub
    59. 'Sub zum starten der Artikelsuche
    60. Private Sub StartArticleSearch()
    61. If TBSearchArticles.Text = "" Then Exit Sub
    62. Dim Search = TBSearchArticles.Text
    63. Dim Searchstring As String = Microsoft.VisualBasic.Replace(_SearchString, "xxooxx", Search)
    64. ArticleBindingSource.FilterX(Searchstring)
    65. End Sub
    66. 'TextChange Event der Suchen Textbox
    67. Private Sub TBSearchArticles_TextChanged(sender As Object, e As EventArgs) Handles TBSearchArticles.TextChanged
    68. StartArticleSearch
    69. End Sub


    Ist aber über einen Editor gemacht - also kein IntelliSense. Wär' also vielleicht garnicht so verkehrt mit nem kleinen Demo-Projekt und ner Hand voll Daten.
    Jo, probier erstma...
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup: