IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

BindingSource.Filter : Ne pas tenir compte des accents


Sujet :

VB.NET

  1. #1
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Points : 275
    Points
    275
    Par défaut BindingSource.Filter : Ne pas tenir compte des accents
    Bonjour,

    Dans ma base de données j'ai des valeurs avec accents.
    Mon appli sélectionne les enregistrements avec la méthode BindingSource.Filter

    Par exemple, si ma table contient un champ "nom" avec des valeurs comme "élève, olive, "eleve", l'instruction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monbindingsource.Filter = "nom Like '%élève%'"
    ne me renverra que "élève".

    Comment modifier cette instruction pour qu'elle me renvoie aussi "eleve" (mais pas "olive") ?
    Bref, comment faire pour que cette instruction soit insensible aux accents ?

    Nota : paradoxalement, l'instruction BindinSource.Sort = "nom" est insensible aux accents : par exemple, le é est bien considéré comme un e dans l'ordre de tri.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    C'est pas évident a priori... Je ne pense pas que tu puisses le faire en utilisant BindingSource.Filter, car le "mini-langage" utilisé dans les expressions de filtre est très limité et ne permet pas de faire ça.

    Par contre, tu pourrais filtrer avec Linq to DataSets, qui permet d'utiliser du code C# ou VB "normal". Cela permettrait d'utiliser une méthode qui enlève les accents, comme celle qui est dispo dans Dvp.NET.

    Par exemple tu pourrais faire un truc comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    monBindingSource.DataSource = maDataTable.AsEnumerable()
        .Where(Function(row) row.Field(Of String)("nom").RemoveDiacritics().Contains("eleve"))
    Pour que ce code marche, il faut ajouter :
    - une référence à System.Data.DataSetExtensions (si elle n'y est pas déjà)
    - une référence à la lib Dvp.NET (le plus simple est de le faire avec Nuget, comme expliqué ici)
    - Imports System.Data et Imports Developpez.Dotnet au début du fichier

    Citation Envoyé par noftal Voir le message
    Nota : paradoxalement, l'instruction BindinSource.Sort = "nom" est insensible aux accents : par exemple, le é est bien considéré comme un e dans l'ordre de tri.
    Normal, c'est l'ordre de tri "naturel" en français. Chaque culture (langue) définit ses propres règles de tri, accessible via CultureInfo.CompareInfo.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Si tu ne préfères pas référencer Dvp.NET, tu peux toujours mettre la méthode RemoveDiacritics dans ton projet, il faut juste la convertir en VB :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    ...
    Imports System.Globalization
    Imports System.Runtime.CompilerServices
    ...
     
    Module StringExtensions
     
        <Extension>
        Public Shared Function RemoveDiacritics(ByVal s As String) As String
     
            If s = Nothing Then
                Throw New ArgumentNullException("s")
            End If
     
            Dim formD As String = s.Normalize(NormalizationForm.FormD)
            Dim chars(formD.Length) As Char
            Dim count As Integer = 0
            For Each c As Char in formD
                If CharUnicodeInfo.GetUnicodeCategory(c) <> UnicodeCategory.NonSpacingMark Then
                    chars(count) = c
                    count = count + 1
                End If
            Next
            Dim noDiacriticsFormD As String = New String(chars, 0, count)
            Return noDiacriticsFormD.Normalize(NormalizationForm.FormC)
        End Function
     
    End Module

  4. #4
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Points : 275
    Points
    275
    Par défaut
    Merci pour ta réponse.
    Bon, je sens qu'on atteint la limite de mes connaissances mais j'ai quand même suivi tes indications.
    J'ai fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Imports Developpez.Dotnet
    Imports System.Data
    Premier soucis, Intellisense ne reconnaît pas "imports System.data.datasetExtension alors que j'ai pourtant bien ajouté la référence.

    Second soucis lié au premier peut-être :
    L'instruction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    monBindingSource.DataSource = maDataTable.AsEnumerable()
        .Where(Function(row) row.Field(Of String)("nom").RemoveDiacritics().Contains("eleve"))
    génère une erreur : "System.notImplementedException : La méthode ou l'opération n'est pas implémentée".

    Dernier soucis : je crains que cette méthode devienne vite assez compliquée avec des expressions de filtre plus complexes comme "A=B AND C LIKE %D%...". Qu'en penses-tu ?

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par noftal Voir le message
    Premier soucis, Intellisense ne reconnaît pas "imports System.data.datasetExtension alors que j'ai pourtant bien ajouté la référence.
    Il faut pas mettre "imports System.data.datasetExtension"....
    System.Data.DatasetExtensions est un assembly (à ajouter en référence), pas un namespace, donc ça s'utilise pas avec Imports.

    Citation Envoyé par noftal Voir le message
    Second soucis lié au premier peut-être :
    L'instruction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    monBindingSource.DataSource = maDataTable.AsEnumerable()
        .Where(Function(row) row.Field(Of String)("nom").RemoveDiacritics().Contains("eleve"))
    génère une erreur : "System.notImplementedException : La méthode ou l'opération n'est pas implémentée".
    Bizarre... Tu peux montrer la pile (stacktrace) de l'exception ?

    Citation Envoyé par noftal Voir le message
    Dernier soucis : je crains que cette méthode devienne vite assez compliquée avec des expressions de filtre plus complexes comme "A=B AND C LIKE %D%...". Qu'en penses-tu ?
    Pas forcément ; perso je trouve pas ça plus compliqué que de générer un filtre en texte, et c'est beaucoup plus souple puisque tu peux utiliser toutes les fonctions du langage VB.

  6. #6
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Points : 275
    Points
    275
    Par défaut
    ci-joint le contenu exact de l'erreur.
    Fichiers attachés Fichiers attachés
    • Type de fichier : txt 1.txt (7,1 Ko, 201 affichages)

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Ah ok, apparemment c'est la BindingSource qui supporte pas une source de type IEnumerable. Essaie d'ajouter .AsDataView() à la fin de l'instruction qui fait le filtrage (après la fin du Where())

  8. #8
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 442
    Points
    4 442
    Par défaut
    bonjour

    IL faut un regroupement d'operateurs :
    ce code renvoie "eleve" et "élève"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    bindingSource1.Filter = " (item Like 'eleve') or (item Like 'élève') "
    bon code.......

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Bah oui mais si la table contient "éleve" ou "elève", il ne sera pas trouvé...

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    674
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 674
    Points : 1 176
    Points
    1 176
    Par défaut
    Bonjour,
    en reprenant la fonction de tomlev, poste 3 (qui est traduite en VB me semble t'il) et en l'utilisant comme ci dessous, ça devrait jouer.
    A voir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            Dim query = _
                From nom In maDataTable.AsEnumerable() _
                Where RemoveDiacritics(nom.Field(Of String)("nom")).Equals("eleve") _
                Select nom
     
            monBindingSource.DataSource = query.AsDataView

  11. #11
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Points : 275
    Points
    275
    Par défaut
    La méthode de MABROUKI n'est en effet pas assez générique. Il faut comprendre que j'ai en 4 ou cinq textboxs dans lesquels je rentre des critères. Certains d'entre eux sont d'ailleurs précédés d'un combobox contenant les valeur "=" et "comme".
    En remplissant un ou plusieurs de ces critères je construis un string sous la forme critère = "A=B AND C LIKE %D% AND ...."
    que j'affecte à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     monbindingsource.Filter = critère
    J'ai donc réussi à faire marcher la méthode de tomlev et Chrismonoye pour un critère A=B (equals) ou A LIKE B (contains).

    Maintenant, tomlev me disait que ce n'était pas compliqué à généraliser pour plusieurs critères élémentaires séparés par un AND. Peux-tu m'expliquer en gros comment tu ferais dans le contexte qui est le mien (construction d'un critère depuis des textbox)

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    En fait, j'avais oublié un truc : si ton DataSet est fortement typé (ce qui est le cas si tu crées les tables avec le designer de VS), tu n'as pas besoin de t'embêter avec row.Field(Of String)("Nom") : tu peux directement écrire row.Nom, ce qui est quand même plus pratique... En combinant ça avec la syntaxe de requête proposée par chrismonoye, ça devient nettement plus lisible...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            Dim query =
                From row In maDataTable.AsEnumerable()
                Where RemoveDiacritics(row.Nom).Contains("eleve")
                Select row
     
            monBindingSource.DataSource = query.AsDataView
    Citation Envoyé par noftal Voir le message
    Maintenant, tomlev me disait que ce n'était pas compliqué à généraliser pour plusieurs critères élémentaires séparés par un AND. Peux-tu m'expliquer en gros comment tu ferais dans le contexte qui est le mien (construction d'un critère depuis des textbox)
    Bah tu peux faire quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
            Dim filtreNom As String = textBoxNom.Text
            Dim filtreAge As Integer = CInt(textBoxAge.Text)
            Dim query =
                From row In maDataTable.AsEnumerable()
                Where row.Nom.RemoveDiacritics().Contains(filtreNom)
                AndAlso row.Age = filtreAge
                Select row
     
            monBindingSource.DataSource = query.AsDataView
    Si tu as besoin que les filtres soient dynamiques, c'est un peu plus compliqué, mais en utilisant PredicateBuilder ça se fait bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
        ' S'il n'y a aucun filtre, le prédicat renvoie True pour accepter toutes les lignes
        Dim predicate = PredicateBuilder.True(Of DataRow)()
     
        ' On ajoute le filtre sur le nom s'il est défini
        If Not String.IsNullOrEmpty(txtNom.Text) Then
            Dim filtreNom As String = textBoxNom.Text
            predicate = predicate.And(Function(row) row.Nom.RemoveDiacritics().Contains(filtreNom))
        End If
     
        ' On ajoute le filtre sur l'âge s'il est défini
        If Not String.IsNullOrEmpty(txtAge.Text) Then
            Dim filtreAge As Integer = CInt(textBoxAge.Text)
            predicate = predicate.And(Function(row) row.Age = filtreAge)
        End If
     
        ' Résultat final
        Dim query = maDataTable.AsEnumerable().AsQueryable().Where(predicate)
        monBindingSource.DataSource = query.AsDataView()
    (note que j'ai ajouté AsQueryable derrière AsEnumerable, parce que le prédicat généré par PredicateBuilder est de type Expression(Of Func(Of T, Boolean)) ; c'est ce qui permet l'utilisation avec Linq to SQL ou Entity Framework par exemple)

    EDIT: autre approche, sans utiliser PredicateBuilder :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
        ' S'il n'y a aucun filtre, le prédicat renvoie True pour accepter toutes les lignes
        Dim query = monDataTable.AsEnumerable()
     
        ' On ajoute le filtre sur le nom s'il est défini
        If Not String.IsNullOrEmpty(txtNom.Text) Then
            Dim filtreNom As String = textBoxNom.Text
            query = From row in query Where row.Nom.RemoveDiacritics().Contains(filtreNom)
        End If
     
        ' On ajoute le filtre sur l'âge s'il est défini
        If Not String.IsNullOrEmpty(txtAge.Text) Then
            Dim filtreAge As Integer = CInt(textBoxAge.Text)
            query = From row in query Where row.Age = filtreAge
        End If
     
        ' Résultat final
        monBindingSource.DataSource = query.AsDataView()
    C'est un peu moins efficace, car cela fait un appel à Where pour chaque condition (au lieu de combiner toutes les conditions en une seule), mais ça marche aussi. L'inconvénient est que ça ne permet pas de faire des OR entre les conditions, seulement des AND, alors que PredicateBuilder le permet...

  13. #13
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Points : 275
    Points
    275
    Par défaut
    Merci Tomlev pour ces indications très complètes.
    Oui, mon filtre est dynamique donc je vais devoir appliquer l'un de tes 2 derniers codes (a priori le second suffirait car je n'ai pas de conditions OR)
    Cela va toutefois m'obliger à revoir pas mal de choses dans mon code actuel sans compter que je maîtrise mal les objets que tu préconises.
    Je vous tiens au courant.

  14. #14
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 442
    Points
    4 442
    Par défaut
    bonjour

    Tu n'as qu' à inclure les clauses parenthesees ( "and" ,"Or", "OrElse") dans ton critere de recherche par concatenation...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    Private Sub btnSearch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click
     
            'on cherche tous les eleves 
            '    => dont le champ ID est > 17
            ' &  => like  quelque chose comme eleve
     
            Dim parO As String = "(" 'ouvrante
            Dim parF As String = ")" ' fermante
            Dim cond1 As String = parO & "ID > " & txtBoxNumero.Text & parF
            Dim cond2 As String = parO & cboNom.SelectedItem.ToString & " Like '%" & txtBoxNom.Text & "%'" & parF
            Dim clause As String = " AND "
            Dim searchCritere As String = cond1 & clause & cond2
            ToolStripStatusLabel1.Text = searchCritere
            bindingSource1.Filter = searchCritere
        End Sub
    bon code....

  15. #15
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    777
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 777
    Points : 275
    Points
    275
    Par défaut
    Ça, c'est ce à quoi ressemble mon code actuellement. C'est de la concaténation de string. La méthode de tomlev est un peu plus compliquée à concaténer.

    EDIT: et surtout, cette méthode basée sur BindingSource.Filter ne permet pas de filtrer indifféremment sur les mots accentués ou non. D'où la création de ce topic.

Discussions similaires

  1. Ne pas tenir compte des accents
    Par jgresse1025 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 02/04/2015, 11h50
  2. [WD19] Requête SQL qui ne doit pas tenir compte des accents
    Par Tchupacabra dans le forum WinDev
    Réponses: 10
    Dernier message: 19/06/2014, 10h30
  3. Ne pas tenir compte des accent dans une requete
    Par prat038 dans le forum SQL
    Réponses: 8
    Dernier message: 07/09/2009, 13h34
  4. "Filter" sur DataBinding sans tenir compte des Accents
    Par dsolheid dans le forum VB.NET
    Réponses: 3
    Dernier message: 23/10/2008, 10h16
  5. Ne pas tenir compte des accents dans une requete
    Par zamanika dans le forum Installation
    Réponses: 8
    Dernier message: 08/11/2004, 19h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo