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

Bases de données Delphi Discussion :

Filtrage des données d'un DBGBrid lors d'un Edit.onChange


Sujet :

Bases de données Delphi

  1. #1
    Membre actif

    Inscrit en
    Mai 2010
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 401
    Points : 294
    Points
    294
    Par défaut Filtrage des données d'un DBGBrid lors d'un Edit.onChange
    Bonsoir a tous,
    j'ai une table des articles qui contient plus de 10 000 article.
    vu a une demande de mon client , il veux afficher tous les articles dans un dbgrid mais avec la possibilité de chercher des articles dans cette dernière .
    pour réaliser ce travail j'ai utilisé une requête SQL (j'utilise Interbase + IBX + Delphi7).
    dans l’événement OnChange du composant Edit1 je filtre mes données avec cette procédure :



    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
    procedure TFMaForm.Edit1Change(Sender: TObject);
    begin
          IF (edit1.text <> '')  then
          begin
                MaQuery.close;
                MaQuery.SQL.Clear;
                MaQuery.SQL.Add('SELECT    CodeArt, Designation,QteStk');
                MaQuery.SQL.Add('FROM  MesArticles');
                MaQuery.SQL.Add('WHERE UPPER(Designation) LIKE  ''%' + UpperCase(edit1.Text) + '%''');
                MaQuery.SQL.Add('ORDER BY CodeArt');
                MaQuery.Active := true;
          else
          begin
                MaQuery.close;
                MaQuery.SQL.Clear;
                MaQuery.SQL.Add('SELECT    CodeArt, Designation,QteStk');
                MaQuery.SQL.Add('FROM  MesArticles');
                MaQuery.SQL.Add('ORDER BY CodeArt');
                MaQuery.Active := true;
     
          end ;
     
    end;
    mais c'est très lourd de faire a chaque caractère une requête sql
    j'ai essayé avec les filtre mais pas moyen.
    avez vous une suggestion SVP !!!

    pour Sergio : SVP cette fois ci ne soit pas sévère avec moi

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 043
    Points : 40 957
    Points
    40 957
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    pour Sergio : SVP cette fois ci ne soit pas sévère avec moi
    c'était juste pour te faire assimiler certaines choses de façon "plus permanente"

    Dans ton code, quelques petits points :

    1 - pour éviter le sautillement de la DBGrid utilise un Maquery.DisableControls à l'entrée de la procédure et à la fin un Maquery.EnableControls
    2- pour la requête cette partie MaQuery.SQL.Add('WHERE UPPER(Designation) LIKE ''%' + UpperCase(edit1.Text) + '%''');est sujette à danger (injection de SQL possible, difficile mais pas inpossible) et de plus s'il s'agit d'une recherche par nom le STARTING WITH sera plus rapide
    (ton client n'a pas dit s'il s'agissait d'une recherche dans le nom LIKE ou dont le nom commence par STARTING)
    3- quelques simplifications sont possibles

    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
     
    procedure TFMaForm.Edit1Change(Sender: TObject);
    begin
       maquery.DisableControls;
       Maquery.Active:=False;
       Maquery.SQL.Text:='SELECT  CodeArt, Designation,QteStk FROM MesArticles'; 
         IF (edit1.text <> '')  then
          begin
    //        MaQuery.SQL.Add('WHERE UPPER(Designation) LIKE  :E');
    //        Maquery.ParamBYName('E').asString:=UpperCase('%'+edit1.Text+'%');
    ou 
              MaQuery.SQL.Add('WHERE UPPER(Designation) STARTING WITH :E');
              Maquery.ParamByName('E').asString:=UpperCase(edit1.Text);  // ou MaQuery.Params[0].asString:=UpperCase(edit1.Text);
          end;
          MaQuery.SQL.Add('ORDER BY CodeArt');
          MaQuery.Active := true;
          Maquery.EnableControls;
     end;
    pour rendre moins facile l'injection de SQL on pourrait aussi traiter le TEdit (longueur max = Taille max de Désignation), pour le Uppercase on peut s'en passer en mettant le TEdit uniquement en majuscule.
    ne connaissant pas assez les IBX je ne sais pas si en plus des paramètres ils acceptent les macros ? ou si un prépare est possible vu que l'on change la requête

    Bien évidemment cette méthode est pénalisante puisque une requête est lancée à chaque fois sur l'ensemble de la table (qui nécessite un Index sur la colonne DESIGNATION pour de bonnes performances) mais dans un environnement multi-utilisateurs (changement de qte sur une autre poste par exemple) le rafraîchissement de la requête serait obligatoire
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre actif

    Inscrit en
    Mai 2010
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 401
    Points : 294
    Points
    294
    Par défaut
    Bonjour Sergio et Merci pour le suivie.
    la recherche doit t être dans n'importe quelle position dans la désignation ,donc je ne peut pas utilisé STARTING WITH .

    Sergio a dit :
    ne connaissant pas assez les IBX je ne sais pas si en plus des paramètres ils acceptent les macros ?
    quel est l'utilité des macros SVP?

    Sergio a dit :
    ne connaissant pas assez les IBX je ne sais pas si en plus des paramètres ils acceptent les macros ? ou si un prépare est possible vu que l'on change la requête.
    Oui un prépare est possible.

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 043
    Points : 40 957
    Points
    40 957
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par aimer_Delphi Voir le message
    quel est l'utilité des macros SVP?
    un exemple avec Firedac (cela aurait put être avec ZEOSDBO, ou RXQuery) , c'est le & qui indique un paramètre dans la Query (mais c'est modifiable par un autre caractère)

    le code dans le TQuery
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT  CodeArt, Designation,QteStk FROM MesArticles &clause ORDER BY CodeArt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
         Maquery.MarcoByName('clause').Clear;
         Maquery.ParamByName('E').Clear;
         IF (edit1.text <> '')  then
          begin
            MaQuery.MacroByName('clause').asRaw:='WHERE UPPER(Designation) LIKE  :E';
            Maquery.ParamBYName('E').asString:=UpperCase('%'+edit1.Text+'%');
          end
    ce qui pourrait se remplacer par un format
    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
    var Clause : String;
    const Q = 'SELECT  CodeArt, Designation,QteStk FROM MesArticles %s ORDER BY CodeArt';
    begin
     Maquery.DisableControls,
     Maquery.Active:=False;
     Clause:='';
      IF (edit1.text <> '')  then
          begin
            clause:='WHERE UPPER(Designation) LIKE  %s';
            clause:=Format(Clause,[QuotedStr('%'+edit1.Text+'%']);
          end
     Maquery.SQL.Text:=Format(Q,[Clause]);
     MaQuery.Active:=True;
     MaQuery.EnableControls;
    end;
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  5. #5
    Membre actif
    Homme Profil pro
    Consultant fonctionnel
    Inscrit en
    Décembre 2014
    Messages
    105
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant fonctionnel

    Informations forums :
    Inscription : Décembre 2014
    Messages : 105
    Points : 235
    Points
    235
    Par défaut
    Bonsoir,
    C'est quoi le but du jeu ? accélérer le process. Tu recrées la requête SQL dans le onchange du tEdit, évidemment c'est pas possible.
    Mais que veux-tu faire ?
    1 - n'afficher QUE les records qui matchent avec le tEdit (c'est ce que tu fais en refaisant ta requete avec le LIKE)
    2 - ou pointer sur le 1er record qui matche avec ton tEdit

    (1) tu n'as pas le choix, tu dois refaire ta requête + ou - comme tu fais ou avec un param dans ton query qy1.params[0].asstring := edit1.text + '%';
    j'utiliserai l'évenement onexit au lieu de onchange, la requete ne se ferai à la fin de la saisie et on pas à chaque key

    (2) si tu veux seulement pointer sur le bon record (mais laisser tous les records dans ton dbgrid),
    tu fais le init et l'open du query avant, il affiche tous les records et fais dans le onchange
    qy1.locate('NOM',edCherche.text,[ loCaseInsensitive, loPartialKey]); (pris dans un de mes codes, NOM étant bien-sûr le nom de mon champ, et edCherche mon tEdit). C'est beaucoup moins gourmand en ressources que refaire la requete.
    Salut.
    solilog

  6. #6
    Membre actif

    Inscrit en
    Mai 2010
    Messages
    401
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 401
    Points : 294
    Points
    294
    Par défaut
    Bonjour a tous ,
    normalement j'ai trouvé la solution.
    c'est d'utiliser ClientDataSet (in memory data) ,
    et pour les requette sql sur ce dataset j'utilise txquery
    http://www.developpez.net/forums/d87...t-open-source/

    Merci a tous.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. basculer des données sur une nouvelle feuille
    Par mary1 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 27/05/2008, 11h47
  2. envoyer des données sur une carte son
    Par khalifa1 dans le forum DirectX
    Réponses: 1
    Dernier message: 26/10/2007, 17h29
  3. Reccupérer des données sur une page Internet
    Par avigeilpro dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 20/05/2007, 05h50
  4. récupérer des données sur une clef USB
    Par mullger dans le forum Périphériques
    Réponses: 6
    Dernier message: 25/09/2006, 18h38
  5. Récupérer des données sur une page HTML
    Par rupeni dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 18/11/2005, 17h22

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