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

Delphi Discussion :

ajuster automatiquement la largeur d'une colonne dans une DBGrid


Sujet :

Delphi

  1. #1
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut ajuster automatiquement la largeur d'une colonne dans une DBGrid
    Bonjour,
    j'ai un souci assez chiant

    j'ai une DBGrid qui affiche les résultats d'une requete (dataset, ...)
    Je voudrais faire un code équivalent au double-clic sur la bordure d'une colonne dans excel ou autre (càd qui ajuste la largeur de la colonne par rapport à la donnée la plus large en affichage dans cette colonne)..

    après qqes recherches, j'ai réussi à écrire ceci (en parcourant tout le dataset pour trouver la cellule de largeur max)

    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    procedure ResizeColumn(Grid: TDbGrid);
    var
      MaxWidth, //Largeur maximale de la colonne
      MinWidth, //Largeur minimale de la colonne
      CurrentWidth: integer; //Largeur actuelle
      FieldSize: integer; //Taille du champ d'après son contenu
    DS: TDataSet;
    BookMark: TBookmark;
    begin
     
    //Pour alléger l'écriture !...
      DS := Grid.DataSource.DataSet;
      with Grid do
      begin
        //Mémoriser la ligne actuellement sélectionnée
        BookMark := DS.GetBookmark;
        //Pour ne pas voir toutes les lignes défiler
        Ds.DisableControls;
        //Parcours de toutes les lignes de l'ensemble de données
    DS.First;
    MaxWidth := Canvas.TextWidth(Columns[SelectedIndex].Title.Caption) + 5;
    MinWidth := 0;
    while not DS.Eof do
    begin
    //Déterminer la largeur en pixels du contenu de l'enregistrement lu
          FieldSize :=
            Canvas.TextWidth(DS.FieldByName(SelectedField.FieldName).AsString) + 5;
          //Réajuster la largeur maximale ?
          if MaxWidth < FieldSize then
            MaxWidth := FieldSize;
          //Réajuster la largeur minimale 
          if MinWidth > FieldSize then
            MinWidth := FieldSize;
          DS.Next;
        end; 
        //Largeur de la colonne cliquée
        CurrentWidth := Columns[SelectedIndex].Width; 
     
        if CurrentWidth <> MaxWidth then 
          CurrentWidth := MaxWidth;
     
        if CurrentWidth < MinWidth then
          CurrentWidth := MinWidth;
        //Affectation de la nouvelle largeur à la colonne
        Columns[SelectedIndex].Width := CurrentWidth;
        //repositionner le curseur de l'ensemble de données
    DS.GotoBookmark(BookMark);
    DS.FreeBookmark(BookMark);
    //Rétablir l'affichage du TDbGrid
        DS.EnableControls;
      end;
    end;
    Le code fonctionne très bien pour ceux que ça intéresse..
    on peut facilement l'adapter d'ailleurs pour ajuster toutes les colonnes du dbGrid..
    sauf que ça prend énormément de temps (le parcours du DataSet)

    ne peut-on pas faire autrement?? plus simplement??

    si qqn a une idée je suis preneur..

    Merci

  2. #2
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 410
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 410
    Points : 5 801
    Points
    5 801
    Par défaut
    salut

    il Faut en conclure que tes champs sont surdimenssionné par rapport au donnée inserer ?

    la solution serait de prendre la taille du champs et de le dimensionner

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  3. #3
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Points : 1 181
    Points
    1 181
    Par défaut
    Je me demande comment il font chez TMS ou DevExpress car c'est instantannée le redimensionnement.

    A+
    On progresse .....

  4. #4
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    c clair...

    ya de super composants chez TMS ou autre qui font ça naturellement

    le pire c'est que un simple double-clic sur la bordure d'une colonne (comme excel, access ou autre) me suffirait.. et je peux même pas le faire..

  5. #5
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 410
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 410
    Points : 5 801
    Points
    5 801
    Par défaut
    salut

    pour optimiser tu peut assigner le with qu'a la fin de la recherche du maxi
    et evite l'acces au canvasavec le textwith remplace le tout betement par un length

    et à la fin seulement tu fait ton maxvalue + 5;

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  6. #6
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    de toute façon l'affectation se fait en dernier lieu..

    Par contre, quand je remplace le cancas.textwidth par un simple Length, j'ai des trucs bizarres..

  7. #7
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Une petite idée comme ça. Chaque colonne correspond à un champ de ta table. Donc tu connais le type de champ de ta table qui lui est limité en longueur. Donc si par exemple ton champ est un string(10). La chaine de caractère 'ZZZZZZZZZZ' te donnera la largueur maximum que tu peux avoir (Z majuscule étant il me semble la lettre la plus large). Si ton champ est un float par exemple de 5,2 alors la chaine '99999.99' te donnera la largeur maximum que tu pourras avoir.

    Donc en faisant ça sur chaque colonne cela t'évite d'aller voir le contenu de chaque ligne.

  8. #8
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 410
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 410
    Points : 5 801
    Points
    5 801
    Par défaut
    salut

    effectivement j'avais mal suivi la boucle tu assigne qu'a la fin
    autant pour moi

    pour ce qui est de length c'est normal, car ce n'est pas la longueur en pixel que tu obtien mais le nombre de caractere
    il faut "recree" un string de la longueur voulu et lui appliquer le textwidth



    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  9. #9
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    bon..

    on peut pas faire un truc non automatique (apres affichage)??

  10. #10
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Citation Envoyé par freestyler
    bon..

    on peut pas faire un truc non automatique (apres affichage)??
    Comment ça ? Ma solution ne te convient pas ?
    Tu peux le faire après affichage. Il te suffit de calculer pour cahque colonne la longueur max en fonction du type de données, c'est tout.

  11. #11
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 410
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 410
    Points : 5 801
    Points
    5 801
    Par défaut
    salut

    a priorie les champs sont surdimensionner par rapport aux valeurs renseigner d'ou ma premiere question

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  12. #12
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Bon on va reprendre car je ne saisi pas tout. D'après le premier message j'avais compris que le redimensionement fonctionnait, mais que ce qui génait c'était le temps que cela prend. Le problème c'est ça ou pas ?

    Car si c'est ça ma solution évite justement de parcourir toutes les lignes et va calculer une largeur max de la colonne en fonction du type de données.

    Citation Envoyé par freestyler
    Le code fonctionne très bien pour ceux que ça intéresse..
    on peut facilement l'adapter d'ailleurs pour ajuster toutes les colonnes du dbGrid..
    sauf que ça prend énormément de temps (le parcours du DataSet)

    ne peut-on pas faire autrement?? plus simplement??

    si qqn a une idée je suis preneur..

    Merci

  13. #13
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    le redimensionnement fonctionne très bine mais prend effectivement beaucoup de temps..

    par contre, j'ai déjà essayé ton idée bien avant..
    le hic c'est que la taille des champs dans la base ne reflètent pas vraiment ce qu'il peut y avoir dans le champ en question.. je veux dire on peut avoir un champ en base fixé à varchar2(50) et avoir des données qui s'étalent sur 3 ou 4 caractères pour leur majorité...
    donc le paramétrage des champs dans la base ne convient pas du tout..mais il est évident que je suis naturellement passé par cette réflexion..

    Maintenant, je demande à savoir si apres constitution de la grid, on pourrait redimensionner cette grid colonne par colonne (par exemple, on double-clique sur la bordure, et la colonne prend la taille du champ le plus large en affichage)

    j'espère que c'est assez clair...

    Merci pour la participation massive à ce post..je crois que ça pourrait faire un excellent post..

  14. #14
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Citation Envoyé par freestyler
    le hic c'est que la taille des champs dans la base ne reflètent pas vraiment ce qu'il peut y avoir dans le champ en question.. je veux dire on peut avoir un champ en base fixé à varchar2(50) et avoir des données qui s'étalent sur 3 ou 4 caractères pour leur majorité...
    Oui c'est en effet un des problèmes de la solution. Mais après à part en parcourant toutes les lignes comme tu le fesais je ne vois pas d'autre solutions. Mais peut être quelqu'un en a t'il une autre.

  15. #15
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    mais comment font ils sous EXCEL?? ou sous Access?? ou sur n'importe quelle application qui gère l'affichage de tableaux??

    un double-clic sur la bordure et la colonne se redimensionne par rapport au champ le plus large...

  16. #16
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Et bien je ne sais pas. Il faut appeller Bill pour lui demander.

  17. #17
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 700
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 700
    Points : 15 043
    Points
    15 043
    Par défaut
    Yop !

    Une piste de réflexion :
    J'ai tout lu en diagonale, si j'ai bien compris, quand tu cliques pour resizer les colonnes, tu fais un appel à la BD ?
    Moi j'y connais rien en BD, mais je suppose que l'affichage doit s'appuyer sur un truc genre StringGrid, est-ce que tu ne pourrais pas t'inspirer de la propriété StringWitdh de la TCustomListView pour tes calculs ?
    Ensuite tu mets ta grille à jour (ColWidths) sans appeler la base.
    Mes 2 cts,
    --
    jp
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  18. #18
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Points : 915
    Points
    915
    Par défaut
    Voici un bon compromis (Vitesse VS Résultat)
    Pour gagner en vitesse, je te propose d'ajuster la largeur des colonnes
    en fonction des éléments que tu as déjà affiché jusqu'à présent.
    C'est un gain réelle en vitesse car tu ne sera pas forcé de parcourir tout
    les champs dans la base de données.

    L'idée, est de calculer au moment même de l'affichage l'espace requis pour
    l'affichage de la donnée (événement OnGetText()) des champs.
    Le .tag de du champs sera utile pour mémoriser la plus grande valeur rencontré jusqu'à
    maintenant. Au moment du redimensionnement des colonnes, on ajuste simplement la
    largeur avec le .tag du champs correspondant. De cette manière, le redimentionnement
    est instantané...par contre, si l'usager navigue plus loin dans les données, il ce pourrait
    que l'opération soit à recommencer.


    Voici ce à quoi ça ressemble:
    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
    29
    30
    31
    32
     
    //=====================================================================
    //== ici OnGetText de mes champs à afficher                         ===
    //== Nom et Prenom                                                  ===
    procedure TForm1.Query1NomGetText(Sender: TField; var Text: String;
      DisplayText: Boolean);
    begin
        Text:=Sender.AsString ;
        //Memorise rapidement le text le plus large affiché dans la colonne
        Sender.Tag:=Max(Sender.tag,DBGrid1.Canvas.TextWidth(Text)+5);
    end;
     
    procedure TForm1.Query1PrenomGetText(Sender: TField; var Text: String;
      DisplayText: Boolean);
    begin
        Text:=Sender.AsString ;
        //Memorise rapidement le text le plus large affiché dans la colonne
        Sender.Tag:=Max(Sender.tag,DBGrid1.Canvas.TextWidth(Text)+5);
    end;
     
    //=====================================================================
    //=== Fonction de Resize
    procedure ResizeColumn(Grid: TDbGrid);
    var
        DS:TDataSet;
    begin
        DS:=Grid.DataSource.DataSet;
        with Grid do
        begin
            Columns[SelectedIndex].Width:=DS.FieldByName(SelectedField.FieldName).Tag;
        end;
    end;
    Il serait bien d'ajouter la largeur des Titres aussi...

    Bref, j'espère que l'idée de plait...
    Comment dupliquer un disque...ça vous intéresse?
    Tutoriel et code source delphi ici

  19. #19
    Membre éprouvé
    Avatar de Andry
    Profil pro
    Informaticien
    Inscrit en
    Juillet 2002
    Messages
    1 164
    Détails du profil
    Informations personnelles :
    Localisation : Madagascar

    Informations professionnelles :
    Activité : Informaticien

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 164
    Points : 1 181
    Points
    1 181
    Par défaut
    J'ai peut être une idée.

    Pourquoi ne pas seulement ajuster la largeur pour les elements visibles.

    Ce n'est qu'une idée

    A+
    On progresse .....

  20. #20
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Citation Envoyé par Eric Boisvert
    Voici un bon compromis (Vitesse VS Résultat)
    Pour gagner en vitesse, je te propose d'ajuster la largeur des colonnes
    en fonction des éléments que tu as déjà affiché jusqu'à présent.
    C'est un gain réelle en vitesse car tu ne sera pas forcé de parcourir tout
    les champs dans la base de données.

    L'idée, est de calculer au moment même de l'affichage l'espace requis pour
    l'affichage de la donnée (événement OnGetText()) des champs.
    Le .tag de du champs sera utile pour mémoriser la plus grande valeur rencontré jusqu'à
    maintenant. Au moment du redimensionnement des colonnes, on ajuste simplement la
    largeur avec le .tag du champs correspondant. De cette manière, le redimentionnement
    est instantané...par contre, si l'usager navigue plus loin dans les données, il ce pourrait
    que l'opération soit à recommencer.
    Je trouve l'idée très bonne en effet. Le seul risque c'est de voir la largeur de la colonne changer au fur et à mesure que l'on se déplace dans la grille.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 7
    Dernier message: 25/03/2011, 11h52
  2. Réponses: 4
    Dernier message: 05/05/2008, 16h16
  3. Récupérer le nom d'une colonne d'une table dans une variable
    Par mimi51340 dans le forum Général Java
    Réponses: 4
    Dernier message: 13/03/2008, 15h23
  4. Recherche une valeur d'une cellule dans une colonne d'une autre feuille
    Par kourria dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 21/06/2007, 14h48
  5. Postionnement dans une colonne dans un DBGrid
    Par Jeankiki dans le forum Bases de données
    Réponses: 7
    Dernier message: 13/01/2005, 01h05

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