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 :

DBGrid: recopier la cellule précédente


Sujet :

Bases de données Delphi

  1. #1
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut DBGrid: recopier la cellule précédente
    FireDAC: DBGrid / FDQuery / MySQL
    Delphi 10.3.3
    VCL

    Bonjour,

    J'ai une grille (DBGrid) qui m'affiche le résultat suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    -------------
    |  id  | Col1|
    -------------
    |  1   |  A  |
    |  2   |     |
    |  3   |  B  |
    |  4   |     |
    |  5   |     |
    |  6   |  C  |
    Lorsqu'une cellule est vide, je souhaiterais simplement recopier la cellule précédente afin d'obtenir ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    -------------
    |  id  | Col1|
    -------------
    |  1   |  A  |
    |  2   |  A  |
    |  3   |  B  |
    |  4   |  B  |
    |  5   |  B  |
    |  6   |  C  |
    Le composant DBGrid possède deux évènements qui sont OnDrawColumnCell et OnDrawDataCell mais je ne sais pas comment récupérer le contenu d'une cellule précédente ?


    merci

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 693
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 128
    Points
    13 128
    Par défaut
    Ce sera difficile avec le DBGrid mais la requête pourrait ressembler à quelque chose comme ceci si col1 est NULL :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT id, COALESCE(col1, (SELECT MAX(col1) FROM matable WHERE id<t.id)) AS col1 FROM matable t

  3. #3
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Merci Andnotor mais ce sont des colonnes calculées donc une requête SQL n'est pas applicable.
    J'ai l'impression que je n'ai pas d'autre choix que de gérer moi-même l'affichage avec une StringGrid et non pas une DBGrid.

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    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 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    J'aurais eu tendance à dire comme AndNotOr, travailler sur le DataSource. Comme il s'agit de données calculées il y a donc calcul, donc c'est là qu'il faudrait travailler au corps.
    un variable globale qui stocke la dernière valeur de la colonne et dans le OnCalcFields quelque chose comme

    si mon calcul -> alors la valeur=variableglobale
    sinon variableglobale=valeur
    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 averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    un variable globale qui stocke la dernière valeur de la colonne et dans le OnCalcFields quelque chose comme
    Oui j'y avais pensé mais ça ne marche pas lorsqu'on manipule le scroll vertical.

    Exemple de grille qui contient 50 lignes mais seules les lignes de 1 à 42 sont visibles.
    - lorsque la grille est affichée la première fois (lignes 1 à 42), oui c'est jouable de mémoriser la dernière ligne qui a été affichée pour afficher la suivante.
    - Si on descend le scroller jusqu'en bas, alors ce sont les lignes 43 à 50 qui sont calculées (on affiche les lignes de 9 à 50): OK ça marche encore dans la mesure ou l'on a mémorisé la ligne 42.
    - MAIS si on remonte le scroller alors d'un cran (en cliquant sur le flèche du haut) il redemande l'affichage uniquement de la ligne 8 et là comme la dernière mémorisée était la ligne 50, ça ne marche pas.

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    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 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Mais normalement, la démarche que j'indique n'a rien à voir avec la grille, puisqu'il s'agit de l'événement onCalcField de la source de données
    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

  7. #7
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Mais normalement, la démarche que j'indique n'a rien à voir avec la grille, puisqu'il s'agit de l'événement onCalcField de la source de données
    Ben si, à mon grand étonnement aussi !
    J'ai mis un point d'arrêt dans l'évènement OnCalcField et lorsque je bouge le curseur de la DBGRid, l'évènement est appellé comme indiqué dans mon précédent post...

    Du coup, j'ai supprimé la DBGrid et je l'ai remplacé par une StringGrid.
    Ce n'est pas plus long d'affichage (identique) et je suis maintenant libre de faire tout ce que je veux !!

    Je ne comprends pas qu'on n'est pas accèss à la procédure Cells[col,row] d'une DBGrid, ne serait-ce qu'en lecture seule, ce serait tellement plus simple !

    Merci

  8. #8
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Bon en fait, avec une TStringGrid c'est énormément plus long qu'avec une DBGrid, je me suis trompé dans mes mesures...

    Du coup je reviens avec la DBGrid.
    Donc dans la procédure OnCalcFields, il me faudrait pouvoir récupérer toute la ligne précédente !
    Je ne sais vraiment pas comment faire ?

  9. #9
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 496
    Points : 2 762
    Points
    2 762
    Billets dans le blog
    10
    Par défaut
    Tu recopies le contenu de ton dataset dans un TFdMemTable (2 lignes de code) que tu modifies à convenance via un "while not eof" avant de l'envoyer vers ton TDBGrid

  10. #10
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Ok merci ALWEBER.
    Je suis entrain de chercher comment utiliser ce composant mais je crains que je passe beaucoup de temps à trouver comment écrire ces deux lignes de codes

  11. #11
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    J'approche !
    - J'ai déposé un composant TFDMemTable sur ma fiche et un TdataSource.
    - J'ai lié le DataSource au TFDMemTable.
    - J'ai lié ma DBGrid au DataSource.

    Après avoir ouvert le FDQuery, j'execute ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      FDMemTable1.CopyDataSet(FDQuery1, [coStructure, coIndexesCopy,
         coIndexesReset, coConstraintsReset, coAggregatesReset,
          coRestart, coAppend]);
    J'ai bien le contenu de la requete dans la grille.
    Mais ensuite, je retombe sur le même problème: Comment récupérer le contenu de la ligne précédente ? ou est l'avantage par rapport au FDQuery ?

  12. #12
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 496
    Points : 2 762
    Points
    2 762
    Billets dans le blog
    10
    Par défaut
    de mémoire le code après le copydataset devrait ressembler à ceci:
    passe le dataset de ton datasource à nil avant de lancer l'opération
    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
     
    stCol : string ;
    FDMemTable1.first ;
    while not FDMemTable1.eof do
    begin
       if FDMemTable1.FieldByName ('Col1').asString <> '' then
        stCOl := FDMemTable1.FieldByName ('Col1').asString
      else
      begin 
        FDMemTable1.edit ;
        FDMemTable1.FieldByName ('Col1').asString := stCol ;
        FDMemTable1.Post ;
      end ;
      FDMemTable1.next ;
    end ;
    FDMemTable1.first ;
    Après remets ton Dataset à FDMemTable1 dans le datasource

  13. #13
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Merci ALWEBER,

    Ca devient bon.
    J'ai fait quelques essais et je pense pouvoir m'en sortir avec tes indications.

    Voici ce que j'ai fait.
    1) Je fais la requête par FDQuery.Open
    2) Je copie la structure dans FDMemTable: Mais cette opération ne me copie pas les champs calculés !!! Pas grave, je vais les recréer.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      FDMemTable1.CopyDataSet(FDQuery1, [coStructure]);
    3) Je rajoute donc les champs supplémentaires (1 seul pour l'exemple)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      FDMemTable1.Close;
      FDMemTable1.FieldDefs.Add('C0', ftString, 30, false);
      FDMemTable1.CreateDataSet;
    4) Je copie les données de FDQuery vers FDMemTable
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      FDMemTable1.CopyDataSet(FDQuery1, [coRestart, coAppend]);
    Cela me copie aussi le contenu de la colonne C0 !

    5) J'applique ton code
    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
     
    Var
      stCol : String;
    begin
      Datasource2.DataSet:=nil;
      FDMemTable1.first ;
      while not FDMemTable1.eof do
      begin
        if FDMemTable1.FieldByName ('C0').asString <> ''  then stCOl := FDMemTable1.FieldByName ('C0').asString
        else
        begin
          FDMemTable1.edit;
          FDMemTable1.FieldByName ('C0').asString := stCol;
          FDMemTable1.Post;
        end;
        FDMemTable1.next;
      end;
      FDMemTable1.first;
      Datasource2.DataSet:=FDMemTable1;
    end;
    Il me reste à faire ça dans mon appli pour voir le résultat en vrai grandeur sur des centaines de colonnes calculées..

  14. #14
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 693
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 128
    Points
    13 128
    Par défaut
    Dommage que tu ne veuilles pas apprendre un minimum SQL...

  15. #15
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    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 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,
    Citation Envoyé par Andnotor Voir le message
    Dommage que tu ne veuilles pas apprendre un minimum SQL...
    Je plussoie !
    C'est surtout la structure des tables (si mes souvenirs d'autres discussions sont exacte une colonne contenant un ensemble de "sous colonnes", une sorte de JSON sans JSON) qui serait réellement à revoir.
    J'ai vu que la même question avait été posée sur le forum Embarcadero avec, en gros les mêmes réponses concernant onCalFields
    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

  16. #16
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Je plussoie !
    C'est surtout la structure des tables (si mes souvenirs d'autres discussions sont exacte une colonne contenant un ensemble de "sous colonnes", une sorte de JSON sans JSON) qui serait réellement à revoir.
    C'est à dire que je ne me suis pas étalé sur "pourquoi la structure de la table avait été faite comme ça".
    Il s'agit d'enregistrer dans une même base, des données provenant de plusieurs sources.
    Chaque source envoie un nombre de données différent et le nom de chaque donnée est aussi différent. De ce fait, il n'est pas possible de créer une table avec x colonnes dont chaque colonne représente une donnée.
    Chaque source peut modifier le nombre et la nature des données à envoyer dans la base à tout moment. Il n'est donc pas envisageable de créer une table par source de données.
    Par conséquent, toutes ces données sont enregistrées dans une colonne unique que je nomme data (de type texte). Cette colonne contient des données sous la forme "C0='du texte';C1='autre texte';C2='toto',C3='data'" etc... Une autre colonne fait référence à une autre table qui me permet d'identifier d'ou vient la source et de nommer chaque colonne (remplacer Cx par le vrai nom) et enfin une colonne contient un timestamp.
    On peut avoir jusqu'à 4000 données par source (donc de C0 à C4000) avec la fréquence d'un envoi toutes les secondes. La base doit pouvoir fonctionner pendant plusieurs mois sans interruption.
    Donc si on partait sur une table de 4000 colonnes, la taille de stockage deviendrait énorme et se compterait très rapidement en plusieurs centaines de Go voire To.
    Afin de ne pas surcharger la base, chaque source n'envoie que les données qui changent (environ 20 à 80 données à chaque fois toutes les secondes), donc on peut se retrouver avec seulement ceci (si,par exemple, deux données sont envoyées): "C3='toto';C5='tata'"

    L'idée de l'utilisation de l'évènement OnCalcFields est donc très appropriée car en me référant à une autre table qui contient la structure des données, il m'est très facile de reconstituer la grille.

Discussions similaires

  1. Réponses: 5
    Dernier message: 26/01/2019, 21h47
  2. Réponses: 1
    Dernier message: 18/09/2006, 12h59
  3. [VBA-E]Trouver et recopier des cellules d'une feuille à une autre
    Par sk8bcn dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 24/08/2006, 16h01
  4. pb de recopie de cellule d'un classeur à l'autre
    Par jimbololo dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 23/05/2006, 15h56
  5. [D7][DBGrid] Texte dans cellule particulière
    Par moulette85 dans le forum Bases de données
    Réponses: 3
    Dernier message: 28/04/2005, 17h49

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