Je m'assure que je n'ai rien compris, car je suis junior.
Pourriez-vous me montrer la ligne de code que je dois corriger ?
Merci.
Version imprimable
Euh, j'ai déjà tout fourni et cela semblait évident mais bon je vais finir le travail ...
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 function CodeBarresExiste(ADOConnection: TADOConnection; const CodeBarres: string): Boolean; var Query: TADOQuery; begin Result := False; Query := TADOQuery.Create(nil); try Query.Connection := ADOConnection; ADOConnection.Open; // Très curieux de l'avoir ici, la connexion devrait être ouvert avant Query.SQL.Text := 'SELECT COUNT(*) AS Cnt FROM PRODUITS ' + 'WHERE C_B1 = :CodeBarres OR C_B2 = :CodeBarres OR ' + 'C_B3 = :CodeBarres OR C_B4 = :CodeBarres OR ' + 'C_B5 = :CodeBarres OR C_B6 = :CodeBarres OR ' + 'C_B7 = :CodeBarres OR C_B = :CodeBarres'; TADOQueryAssistant.Bind(Query, 'CodeBarres', CodeBarres); // remplace Query.Parameters.ParamByName('CodeBarres').Value := CodeBarres; Query.Open(); // Indispensable APRES le Bind ! Result := Query.FieldByName('Cnt').AsInteger > 0; finally Query.Free; end; end;
La remarque de ShaiLeTroll est juste, ça me restait dans la tête sans mettre le doigt dessus, une des raisons pour laquelle je ne suis pas fan des composants ADO !
Dans votre cas précis, puisqu'il n'y a qu'un seul paramètre
Ceci devrait suffire à la place de Query.Parameters.ParamByName('CodeBarres').Value := CodeBarres;Ceci ne serait certes pas arrivé si la suggestion de Bardoire37 était appliquéeCode:
1
2 for i:=0 to AQuery.Parameters.Count - 1 do AQuery.Parameters[I].Value:=CodeBarres;
Ce que te dit ShaiLeTroll c'est qu'avec une TADOQuery, tu ne peux pas avoir plusieurs fois le même paramètre "CodeBarre" dans ta requête.
Lorsque tu affectes la valeur avec, on dit aussi que l'on "Bind" le paramètre (on lie le nom à un type et une valeur)Code:Query.Parameters.ParamByName('CodeBarres').Value := CodeBarres;
Seule la première occurrence sera affectée, les autres seront laissés à un état indéterminé
Il te donne une méthode pour contourner ce problème
Ensuite tu peux aussi dans requête mettre les paramètres style Codebarre1, Codebarre2, CodeBarre3, etc... et tous leur affecter la même valeur, ça fonctionnera, mais c'est moins élégant
On peut avoir plusieurs fois le même paramètre mais faut savoir le gérer en propageant la valeur à chaque paramètre ... mais vu le faible niveau mieux vaut opter pour un code simple non réutilisable et clé en main ! :aie:
Oublions tout le reste, voici la nouvelle fonction auto-suffisante :
Code:
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 function CodeBarresExiste(ADOConnection: TADOConnection; const CodeBarres: string): Boolean; var Query: TADOQuery; I: Integer; begin Result := False; Query := TADOQuery.Create(nil); try Query.Connection := ADOConnection; ADOConnection.Open; // Très curieux de l'avoir ici, la connexion devrait être ouvert avant Query.SQL.Text := ' SELECT COUNT(*) AS Cnt ' + ' FROM PRODUITS ' + ' WHERE C_B1 = :CodeBarres OR C_B2 = :CodeBarres ' + ' OR C_B3 = :CodeBarres OR C_B4 = :CodeBarres ' + ' OR C_B5 = :CodeBarres OR C_B6 = :CodeBarres ' + ' OR C_B7 = :CodeBarres OR C_B = :CodeBarres '; // C_B ou C_B8 ? cela change selon les versions de fonction, je vous laisse ajuster cela for i := 0 to Query.Parameters.Count - 1 do Query.Parameters[I].Value := CodeBarres; Query.Open(); // Indispensable APRES le Bind ! Result := Query.FieldByName('Cnt').AsInteger > 0; finally Query.Free; end; end;
Le Helper n'existe pas en D7, je te laisse donc faire un Assistant à l'ancienne genre
Cher ShaiLeTroll ShaiLeTroll,Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 class procedure TADOQueryAssistant.Bind(AQuery: TADOQuery; const AParamName: string; const AParamValue: Variant; const AParamDateType: TDataType; const AParamDirection: TParameterDirection = pdInput); var i: Integer; ParamObj: TParameter; begin for I := in AQuery.Parameters.Count - 1 do begin ParamObj := AQuery.Parameters[I]; if SameText(ParamObj.Name, AParamName) then begin ParamObj.Direction := AParamDirection; ParamObj.DataType := AParamDateType; ParamObj.Value := AParamValue; end; end; end;
Je tiens tout d'abord à exprimer ma gratitude pour votre précieuse assistance précédente.
En pièce jointe, vous trouverez le code en question. Malheureusement, il génère une erreur que je n'arrive pas à résoudre malgré mes efforts.
J'apprécierais énormément si vous pouviez jeter un coup d'œil et me fournir des conseils ou des suggestions pour le corriger.
Votre expertise a été d'une grande aide par le passé, et je suis convaincu que vos conseils seront tout aussi bénéfiques cette fois-ci.
Je vous remercie d'avance pour votre précieuse assistance.
Cordialement,
Cher ShaiLeTroll,
Je voulais prendre un moment pour vous exprimer ma profonde gratitude pour votre assistance précieuse. Votre code a résolu le problème que je rencontrais, et tout fonctionne parfaitement maintenant !
Je suis vraiment reconnaissant de votre expertise et de votre générosité à partager vos connaissances. Votre contribution a été extrêmement utile, et je ne pourrais pas être plus satisfait du résultat.
Merci encore pour votre temps et votre soutien. Si jamais vous avez besoin d'aide à l'avenir, n'hésitez pas à me le faire savoir. Je suis là pour vous.
Merci aussi à sergio_is_back et à SergioMaster Votre soutien a été inestimable, et je suis extrêmement reconnaissant d'avoir pu bénéficier de votre expertise. Si jamais je peux vous rendre la pareille à l'avenir, n'hésitez pas à me le faire savoir.
Juste pour le coté educatif même si cela ne sert plus à rien
oui c'était for itérator et j'ai juste pas tout corrigé en D7, j'ai oublié de finir la transformation donnant un code faux dans toutes versions.Code:for I := in AQuery.Parameters.Count - 1 do
D7
D10Code:for I := 0 to AQuery.Parameters.Count - 1 do
Sur une TStringList, c'est plus compréhensible que sur un TCollectionCode:for It in AQuery.Parameters do
D7
Code:
1
2
3
4
5
6
7
8
9
10 var I: Integer; S: string; begin for I := 0 to StringList.Count - 1 do begin S := StringList.Strings[I]; ShowMessage(S); end; end;
En D10Code:
1
2
3
4
5
6 var I: Integer; begin for I := 0 to StringList.Count - 1 do ShowMessage(StringList.Strings[I]); end;
Code:
1
2
3
4
5
6 var S: string; begin for S in StringList do ShowMessage(S); end;
Juste pour le coté éducatif aussi :
C'est vrai que les class helpers n'existent pas en Delphi 7 mais on peut toujours s'en sortir avec un hacking de la classe TADOQuery, exemple :
Puis on l'utilise comme ça :Code:
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 unit MyADOQuery; interface uses Variants, Classes, SysUtils, DB, ADODB; type TADOQuery = class(ADODB.TADOQuery) public procedure Bind(const AParamName: string; const AParamValue: Variant; const AParamDateType: TDataType; const AParamDirection: TParameterDirection = pdInput); end; implementation procedure TADOQuery.Bind(const AParamName: string; const AParamValue: Variant; const AParamDateType: TDataType; const AParamDirection: TParameterDirection); var i: Integer; ParamObj: TParameter; begin for I := 0 to Self.Parameters.Count - 1 do begin ParamObj := Self.Parameters[I]; if SameText(ParamObj.Name, AParamName) then begin ParamObj.Direction := AParamDirection; ParamObj.DataType := AParamDateType; ParamObj.Value := AParamValue; end; end; end;
Code:
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 implementation {$R *.dfm} uses MyADOQuery; // A mettre dans l'implémentation de chaque unité où l'on veut l'utiliser { ......... Autre code............... } function CodeBarresExiste(ADOConnection: TADOConnection; const CodeBarres: string): Boolean; var Query: TADOQuery; I: Integer; begin Result := False; Query := TADOQuery.Create(nil); try Query.Connection := ADOConnection; ADOConnection.Open; // Très curieux de l'avoir ici, la connexion devrait être ouvert avant Query.SQL.Text := ' SELECT COUNT(*) AS Cnt ' + ' FROM PRODUITS ' + ' WHERE C_B1 = :CodeBarres OR C_B2 = :CodeBarres ' + ' OR C_B3 = :CodeBarres OR C_B4 = :CodeBarres ' + ' OR C_B5 = :CodeBarres OR C_B6 = :CodeBarres ' + ' OR C_B7 = :CodeBarres OR C_B = :CodeBarres '; // C_B ou C_B8 ? cela change selon les versions de fonction, je vous laisse ajuster cela Query.Bind('CodeBarres',CodeBarres,ftString,pdInput); // On fait le BIND maintenant Query.Open(); // Indispensable APRES le Bind ! Result := Query.FieldByName('Cnt').AsInteger > 0; finally Query.Free; end; end;