ADOTable et DBText ou TLabel

Résolu
PValentin Messages postés 9 Date d'inscription jeudi 28 novembre 2019 Statut Membre Dernière intervention 14 février 2021 - Modifié le 29 nov. 2019 à 08:49
PValentin Messages postés 9 Date d'inscription jeudi 28 novembre 2019 Statut Membre Dernière intervention 14 février 2021 - 6 déc. 2019 à 21:48
Bonjour,
Sur l'appli que je suis en train de faire et qui est presque finie, j'ai un problème. Je cherche depuis une dizaine de jours (Google, forums divers, aide de delphi,...) mais je n'ai rien trouvé.
J'ai une base de donnée sous Access avec une dizaine de champs. Dans Delphi, j'ai entre autres une Form avec des DBEdit, des DBComboBox, des DBImage et un DBNavigator, tout ça pour alimenter ma base, et ça fonctionne bien.
Pour finir mon appli, j'ai ajouté une Form qui comprend une cinquantaine de Timage et sous chaque TImage un TLabel (j'ai essayé aussi avec un DBEdit).
Ce que je voudrai, c'est que à l'ouverture de cette Form, les TImages soient remplis avec le champ correspondant de mon ADOTable, et que les TLabel (ou DBEdit) soient remplis avec un autre champ de ma base, ceci avec une boucle pour passer tous les enregistrements de la base.
En ce qui concerne les images, ça fonctionne très bien, mais avec les TLabel ou DBEdit, ça ne marche pas.
Voici mon code :

procedure TForm4.FormActivate(Sender: TObject);
var
  bmp: TBitmap;
  i: Integer;
begin
  Form4.ADOTable5.close;
  Form4.ADOTable5.open;
  for i := 1 to Form4.ADOTable5.RecordCount do
    try
      Form4.ADOTable5.RecNo := i;
      bmp := TBitmap.Create;
      bmp.Width := 224;
      bmp.height := 224;
      bmp.Assign(Form4.ADOTable5.Fields[1]);
      (Components[i-1] as TImage).Picture.Assign(bmp);
    finally
      bmp.Free;
    end;

  for i := 1 to Form4.ADOTable5.RecordCount do
      Form4.ADOTable5.RecNo := i;
      (Components[i] as TLabel).Caption := AdoTable5.Fields.Fields[0].AsString;
end;

end.


Merci pour votre aide, je tourne en rond !


PS :
1) Lorsque je lance l'exécution, j'ai le message d'erreur suivant :
> Transtypage de classe incorrect.

Je vois à peu près ce que ça signifie, mais je ne comprends pas pourquoi.

2) J'ai fait 2 boucles 'for' séparées pour isoler l'erreur, mais si par bonheur la seconde marche un jour, je l'inclurai dans la première.

10 réponses

Salut, écrit en live donc pas testé et à adapter...
pour info un exemple avec un memo...
ADOTable5.Close;
ADOTable5.Open;
Memo1.Clear;
ADOTable5.First;
while not ADOTable5.Eof do
begin
  Memo1.Lines.Add(ADOTable5.Fields[0].AsString);
  ADOTable5.Next;
end;

et en reprenant ...
ADOTable5.Close;
ADOTable5.Open;
ADOTable5.First;
for I := 0 to ComponentCount -1 do
begin
  if Components[I] is TImage then
  begin
    try
      bmp := TBitmap.Create;
      bmp.Width := 224;
      bmp.Height := 224;
      bmp.Assign(ADOTable5.Fields[1]);
      (Components[I] as TImage).Picture.Assign(bmp);
    finally
      bmp.Free;
    end;
    ADOTable5.Next;
  end;
  if Components[I] is TLabel then
  begin
    (Components[I] as TLabel).Caption := ADOTable5.Fields[0].AsString;
    ADOTable5.Next;
  end;
end;
@+
1
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
Modifié le 30 nov. 2019 à 19:46
Pour rester dans ton approche, il faut parcourir tous les composants de la fiche, et incrémenter un index correspondant aux images et strings de ta base, ça fait un truc comme ça (tu n'as plus qu'à remplacer les pointillés par ton code qui charge les champs de ta base dans les composants de la fiche) :

var
  i: Integer;
  IndexImage: Integer;
  IndexString: Integer;
begin
  IndexImage := -1;
  IndexString := -1;
  for i := 0 to ComponentCount - 1 do
  begin
    if Components[i] is TImage then
    begin
      Inc(IndexImage);  // tu incrémentes l'index de ta base
      // là tu charges l'image de ta base qui correspond à IndexImage
      // ...
      // ...
    end
    else
    if Components[i] is TLabel then
    begin
      Inc(IndexString);  // tu incrémentes l'index dans ta base
     // là tu affiches le string de ta base dont l'index est IndexString
     // ...
     // ...
    end;
  end;
end;


Il vaut mieux utiliser un index différent pour l'image et pour le string, car si des composants sont interposés entre l'image le caption qui s'y rapporte, ça fausse tout...
--
1
PValentin Messages postés 9 Date d'inscription jeudi 28 novembre 2019 Statut Membre Dernière intervention 14 février 2021
Modifié le 30 nov. 2019 à 10:09
Salut Yanb,

Merci pour ta réponse. J'ai testé ta solution :

begin
ADOTable5.First;
  for j := 1 to ADOTable5.RecordCount do
    if Components[j] is TLabel then
      begin
        (Components[j] as TLabel).Caption := ADOTable5.Fields[0].AsString;
        ADOTable5.Next;
      end;
end;


Je n'ai plus le message >Transtypage de classe incorrect
Par contre, tous les TLabels restent avec leur caption d'origine : Label1, Label2, Label3, .....

J'ai utilisé ADOTable5.RecordCount et non ComponentCount parce que le nombre d'enregistrements de la base est pour l'instant inférieur à celui des composants.

Si je teste avec un memo, ça fonctionne, mais c'est bien ça le problème, il n'y a qu'un memo, donc pas besoin d'incrémenter le numéro du composant.

Si ça te parle, ou si quelqu'un a déja eu ce cas...

PS : Comment fait-on pour formater les lignes de codes sur les messages du forum ?
0
@karamel Messages postés 1854 Date d'inscription vendredi 9 mai 2008 Statut Modérateur Dernière intervention 8 avril 2024 153
Modifié le 1 déc. 2019 à 09:28
Comment fait-on pour formater les lignes de codes sur les messages du forum ?
un petit tuto
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
30 nov. 2019 à 19:33
Salut,

" J'ai utilisé ADOTable5.RecordCount et non ComponentCount parce que le nombre d'enregistrements de la base est pour l'instant inférieur à celui des composants"

Dans ce cas, tu ne parcours pas tous les composants de ta fiche, donc il se peut que tu n'atteignes jamais aucun TLabel !

--
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Salut,
Ecrit en live...
Changeons d'approche, comme le dit jappe que je salut au passage, beaucoup de chose dans ton code peut fausser le résultat que tu attends, attention aussi à ce que tes TLabel ne soit pas dans des conteneurs comme par exemple un TGroupbox...
Si ce n'est pas le cas avec une bonne méthode degueux avec FindComponent ça doit donner un truc du genre (un tableau de composant serait quand même mieux) et en supposant que Label1 est égal à l'index 1 de la table etc...
...
var
  MyLabel: TLabel;
begin
  ADOTable5.Close;
  ADOTable5.Open;
  ADOTable5.First;
  i := 0;
  while not ADOTable5.Eof do
  begin
    i := i+1;
    MyLabel := FindComponent(Format('Label%d', [i])));
    if MyLabel <> nil then
      MyLabel.Caption := ADOTable5.Fields[0].AsString; 
    ADOTable5.Next;
  end;
end;
@+
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
Modifié le 1 déc. 2019 à 14:12
Salut Yanb,
tout à fait d'accord, on peut parcourir la table et là, pour chaque enregistrement, on utilise FindComponent.
Il suffit de nommer logiquement les composants TLabel et TImage destinés à recevoir les data.
Est-ce plus simple ? Il faudrait avoir une vue plus précise du projet, son interface, sa finalité, tout ça, pour trancher...
0
PValentin Messages postés 9 Date d'inscription jeudi 28 novembre 2019 Statut Membre Dernière intervention 14 février 2021
1 déc. 2019 à 14:59
Bonjour Yanb et japee,

Tout d'abord, merci à vous 2 d'avoir bien voulu vous pencher sur mon projet et des différentes solutions proposées.
Mon projet, c'est une gestion des plaques de muselets (capsules) de champagnes ou mousseux.
J'ai d'abord une Form qui est un splashScreen, puis une Form qui est le menu principal.
Dans ce menu, j'ai différentes options. Entre autres, j'appelle une Form qui me sert à remplir les champs de ma base de données (sous Access), ça fonctionne bien. J'ai d'autres options pour sauvegarder la base ou la restaurer, ça marche aussi. J'ai également l'option qui appelle une Form toute simple (la fameuse Form4) sur laquelle j'ai mes Timages et mes TLabels qui sont sensés afficher mes capsules possédées.

Pour info, je ne suis pas très avancé en connaissances de Delphi, mais ça me passionne et j'en découvre tous les jours d'avantage.

Voici ce que j'ai testé dernièrement et là, je m'arrache les cheveux :

J'ai gardé ma Form 4 où j'ai mes TImages et mes TLabels. Je n'ai gardé que ce code :

procedure TForm4.FormShow(Sender: TObject);
var
i: Integer;
IndexString : Integer;
begin
   Form4.ADOTable5.close;
   Form4.ADOTable5.open;
   ADOTable5.First;
   IndexString := -1;
   for i := 0 to ADOTable5.RecordCount -1 do
   begin
      if Components[i] is TLabel then
      begin
         Inc(IndexString);
         (Form4.Components[IndexString] as TLabel).Caption := ADOTable5.Fields[0].AsString;
         ADOTable5.Next;
      end;
   end;
end;


Ca fonctionne très bien, mes TLabels ont bien comme caption le texte que j'attends.

Ensuite, j'ai créé une autre Form (Form6) sur laquelle j'ai également des TImages et des TLabels. J'ai appliqué ce code :


procedure TForm6.FormActivate(Sender: TObject);
var
  bmp: TBitmap;
  i: Integer;

begin
  Form6.ADOTable1.close;
  Form6.ADOTable1.open;
  for i := 1 to Form6.ADOTable1.RecordCount do
    try
      Form6.ADOTable1.RecNo := i;
      bmp := TBitmap.Create;
      bmp.Width := 110;
      bmp.height := 150;
      bmp.Assign(Form6.ADOTable1.Fields[1]);
      (Components[i-1] as TImage).Picture.Assign(bmp);
    finally
      bmp.Free;
    end;


Lorsque j'appelle cette Form6 par mon menu, ça fonctionne très bien, j'ai bien mes images à leur place.

Mais lorsque je mets ces 2 codes sur la même form et que je l'appelle, ça ne marche plus : j'ai bien les TLabels corrects mais je n'ai plus aucune image, sans message d'erreur.

Qu'en pensez-vous ?

japee, tu dis :

>Salut Yanb,
>tout à fait d'accord, on peut parcourir la table et là, pour chaque enregistrement, on >utilise FindComponent.
>Il suffit de nommer logiquement les composants TLabel et TImage destinés à recevoir >les data.

Comment faire ?

J'avoue que si ça continue, je vais laisser tomber cette idée de photos de mes plaques (capsules) mais ça serait dommage, bien sûr.

En tout cas, merci encore à vous deux.
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
Modifié le 2 déc. 2019 à 11:25
Salut,
c'est normal que tu n'ai pas le résultat que tu recherches, ton code n'a pas la logique que tu espères.
Tu fais une boucle sur les valeur de ta table, disons par exemple 2 valeur et tu incrémentes Components[I] en fonction de RecordCount de la table.
Si tu as 2 TLabel et 2 TImage, donc ComponentCount = 4, toi tu attends RecordCount = 1 = Component[1] = Image1 = Label1 et le suivant RecordCount = 2 = Component[2] = Image2 = Label2, hors ce n'est pas le cas. Ceci dépend de l'ordre de création de tes composants sur ta fiche et c'est aussi pour ça que Japee indexé et faisait la boucle sur ComponentCount, car on recherche 4 composants pour 2 lignes de la table.
Tu as du faire un copier coller des TImage et des TLabel de tes form, donc ordre de création sur la fiche est probablement Label1,Label2...ensuite Image1,Image2,...si tu supprimes et recréés ton Image1 elle va se retrouver à la fin de tout tes composants...
Regarde l'ordre de création de tes composants sur ta fiche pour comprendre avec des copier coller supprime etc...
for I := 0 to ComponentCount - 1 do
  Memo1.Lines.Add(Format('I=%d => Composant=%s',[I,Components[I].Name]));

D'où ma proposition d'utiliser la fonction FindComponent (Regarde L'aide de FindComponent), cette fonction permet de retrouver dans la form le composant en fonction de son nom et de ne plus se soucier de son ordre de création.
J'avais mis un exemple seulement pour les TLabel (non testé et avec des erreurs je viens de voir) pour que tu comprennes et recherches le fonctionnement de cette fonction.
Japee dit : Il suffit de nommer logiquement les composants TLabel et TImage destinés à recevoir les data.
La logique dans ton cas est que l'enregistrement numéro 1 de la table va correspondre à Image1 et à Label1, l'enregistrement numéro 2 à Image2 et Label2.
D'où mon utilisation de Format('Label%d', [I]) dans FindComponent si I=1 la fonction Format remplace %d par 1 => donc au final elle recherche Label1 (Regarde l'aide de format).
Attention si tu met comme nom Label1 pour un TImage ça plante, car on recherche un nom et on l' affecte à un type de composant précis, si tu met label1 au lieu de Label1 FindComponent ne trouvera pas le composant car il est sensible à la case, d'où logique de nommage des composants.
Voici le code qui doit fonctionner avec des commentaires.(non testé avec une base)
procedure TForm1.FormActivate(Sender: TObject);
var
  NumCp: Integer;//Numéro du composant
  MyImage: TImage;
  MyLabel: TLabel;
begin
  ADOTable1.Close;
  ADOTable1.Open;
  ADOTable1.First;//On se met au début de l'enregistrement de la table
  NumCp := 0;//On met le numéro du composant à 0
  while not ADOTable1.Eof do//On va boucler jusqu'à la fin des valeurs de la table
  begin
    NumCp := NumCp + 1;//On incrémente le numéro de composant recherché
    MyLabel := TLabel(FindComponent(Format('Label%d', [NumCp])));//On recherche le composant de Nom 'LabelX' où X = NumCp
    if MyLabel <> nil then//Si on a trouvé un composant nommé 'LabelX' sur la fiche où X = NumCp
      MyLabel.Caption := ADOTable1.Fields[0].AsString;//On affecte la valeur Fields[0].AsString au composant trouvé
    MyImage := TImage(FindComponent(Format('Image%d', [NumCp])));//On recherche le composant de Nom 'ImageX' où X = NumCp
    if MyImage <> nil then//Si on a trouvé un composant nommé 'ImageX' sur la fiche où X = NumCp
    begin
      //Si c'est un bitmap directement dans la base
      MyImage.Width := 110;//On met la largeur du composant à 110
      MyImage.Height := 150;//On met la hauteur du composant à 150
      MyImage.Picture.Assign(ADOTable1.Fields[1]);//On affecte la valeur Fields[1] au composant trouvé
      //Si c'est un chemin de fichier bitmap dans ta base
      {MyImage.Width := 110;
      MyImage.Height := 150;
      MyImage.Picture.LoadFromFile(ADOTable1.Fields[1].AsString);//On affecte la valeur Fields[1].Astring au composant trouvé}
    end;
    ADOTable1.Next;//On passe à l'enregistrement suivant de la table
  end;
end;
@+
0
japee Messages postés 1727 Date d'inscription vendredi 27 décembre 2002 Statut Modérateur Dernière intervention 6 novembre 2021 8
2 déc. 2019 à 11:15
Salut les gars,

C'est presque un tutoriel sur l'usage de FindComponent et de la fonction Format (si utile !) que tu nous fais là, yanb !

/!\ ATTENTION /!\

PValentin, il semble que tu utilises plusieurs Forms.
Dans ces conditions, si FindComponent s'applique au Form où tu l'utilises, c'est OK.
Si FindComponent doit parcourir les composants d'un autre Form, attention à bien le préciser, par exemple "Form4.FindComponent(...)", Form5.FindComponent(...)"
Ça paraît évident, mais on peut s'y planter...

Sinon, y'a pas de raison que ça marche pas.

Bon courage !
0
cs_yanb Messages postés 271 Date d'inscription lundi 27 octobre 2003 Statut Membre Dernière intervention 7 juillet 2022 14
2 déc. 2019 à 12:36
Salut Japee,
non je crois que c'est foxi qui a fait le tutoriel sur format à l'époque ;) mais une explication pour quelqu'un qui dit "ça me passionne et j'en découvre tous les jours d'avantage" donc autant essayer d'être clair et puis ça change des : je veux un code, comment on fait, j'ai une application et j'arrive pas...sans une un bout de code à la fin...@+
0
PValentin Messages postés 9 Date d'inscription jeudi 28 novembre 2019 Statut Membre Dernière intervention 14 février 2021
2 déc. 2019 à 13:25
Salut Yannb et Japee,
Vos commentaires m'ont fait chaud au coeur !
J'avais testé le code de Yannb : MyLabel := FindComponent(Format('Label%d', [i])));
J'ai eu un message d'erreur, et je crois que c'est ce qui m'a déprimé, j'y croyais tant !
Effectivement, j'aurais dû étudier plus à fond les FindComponent et Format, mais j'ai passé mon temps à tester plein d'autres essais (j'y ai même passé une bonne partie de la nuit), tout ça pour le même résultat.
Je vais essayer les méthodes que vous me préconisez, et surtout, je vais chercher à en comprendre le fonctionnement.
En tout cas, merci encore, vous vous intéressez à mon problème, vous avez la patience d'expliquer, c'est génial.
Je vous tiendrai au courant, mais peut-être pas dans l'immédiat.

@+
0
PValentin Messages postés 9 Date d'inscription jeudi 28 novembre 2019 Statut Membre Dernière intervention 14 février 2021
4 déc. 2019 à 08:51
Salut !
Après quelques jours d'absence, j'ai appliqué la dernière solution proposée et CA MARCHE !
J'ai compris le fonctionnement de FindComponent et maintenant, je saurai où et quand m'en servir. En ce qui concerne Format, le pire c'est que je l'ai déja utilisé dans une autre partie de mon application !
J'ai aussi constaté que les composants se numérotent différemment de ce que je pensais, et ça c'est important.
Au final, ma Form comprend 104 TImages et 104 TLabel. Au départ, ça ne fonctionnait pas parce que j'ai essayé de renommer les composants pour qu'ils soient dans l'ordre (j'avais copié-collé, j'en avais ajouté, j'en avais supprimé, etc.) mais ça ne fonctionnait plus. J'ai donc créé une nouvelle Form et j'ai ajouté tous les composants un par un, et ça marche à merveille.
Maintenant, je vais faire une selection dans ma base pour n'avoir que 104 enregistrements, puis 104 nouveaux, puis 104 nouveaux, etc. parce que la base peut (pourrait) contenir des milliers d'enregistrements. Mais ça, je ne pense pas que ça me pose problème.
Au départ du projet, c'était une excuse pour apprendre d'avantage (ce qui a été le cas), mais finalement, je suis assez content de moi et ça me servira pour une nouvelle lubie, la placomusophilie (collection de plaques de muselets !).
Encore mille mercis !!!
@+ et bonne journée

PS: J'ai un gros problème qui vient de se produire, je pense que je vais être obligé de reformater mon disque dur système et réinstaller tout mon bazar, donc je serai 'absent' encore quelques temps !
0
PValentin Messages postés 9 Date d'inscription jeudi 28 novembre 2019 Statut Membre Dernière intervention 14 février 2021
6 déc. 2019 à 21:48
Bonsoir,
Ca y est, j'ai tout réparé. Je me suis ramassé un p... de virus, heureusement que je sauvegarde régulièrement mes disques durs.
Pour en revenir à mon problème sur mon appli, ça fonctionne donc je vais pouvoir mettre résolu.
Encore merci à Yanb et Japee.
Longue vie au forum et bonne programmation (et bonnes fêtes de fin d'année !!!)

PValentin
0
Rejoignez-nous