Record Vs Packed Record

Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
- - Dernière réponse : cs_MAURICIO
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
- 18 janv. 2013 à 18:50
Bonjour à tous!

j' ai il y a quelques temps eu des problèmes aléatoires de mémoire dans une de mes applications qui utilisait des arrays de record:

monRecord: Record
cod: Integer;
Descr: String;
end;

MonTableau: Array of monRecord;


Le problème surevenait lorsque le tableau avait beaucoup d' éléments.
Après avoir pensé plusieurs fois au suicide, j' ai modifié la déclaration de mon record en ajoutant "packed" (j' ai vu ça sur le net) :
monRecord: packed Record

Ma question est: pourquoi ça marche? Je sais, c' est con, mais le fait que ça marche n' est pas satisfaisant en soi.
Merci à vous de m' aider à comprendre pourquoi ...

a+

Composants Cindy pour Delphi
Faites une donation.
Afficher la suite 

20 réponses

Messages postés
4200
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
2 janvier 2019
26
0
Merci
le fait d'ajouter packed permet d’aligner les champs et de compresser certaines références en mémoire paginée.

idéalement, il faudrait utiliser une TList pour ce genre d'elements plutôt qu'un array dynamique ;)



________________________________________________________
besoin de câbles audio, vidèo, informatique pas cher ?
Commenter la réponse de f0xi
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
0
Merci
"idéalement, il faudrait utiliser une TList pour ce genre d'elements plutôt qu'un array dynamique ;) "
Merci Foxi!


Composants Cindy pour Delphi
Faites une donation.
Commenter la réponse de cs_MAURICIO
Messages postés
675
Date d'inscription
jeudi 17 avril 2008
Statut
Membre
Dernière intervention
19 février 2019
10
0
Merci
voila ce dit Delphi sur packed :
Par défaut, les valeurs d'un type structuré sont alignées sur des limites de mot ou de double-mot afin de disposer d'un accès plus rapide. Quand vous déclarez un type structuré, vous pouvez spécifier le mot réservé packed pour implémenter le stockage compressé des données. Par exemple :

type TNombres = packed array[1..100] of Real;

L'utilisation de packed ralentit l'accès aux données et, dans le cas d'un tableau de caractères, nuit à la compatibilité (pour plus d'informations, voir Gestion de la mémoire).


Comme le dit F0xy, j'utilise maintenant des Tstringlist pour stocher toutes mes infos : ça se charge et se sauve facilement (voir CSV de F0xy)


Dubois77
site perso
Commenter la réponse de dubois77
Messages postés
192
Date d'inscription
mercredi 29 décembre 2004
Statut
Membre
Dernière intervention
2 octobre 2014
1
0
Merci
Mauricio,

Ici j'ai trouvé cela :

The Packed keyword tells Delphi to minimise the storage taken up by the defined object.

Normally, complex data types, such as records have their elements aligned to 2, 4 or 8 byte boundaries, as appropriate to the data type. For example, a Word field would be aligned to a 4 byte boundary.

Records are also padded to ensure that they end on a 4 byte boundary.

These alignments ensure optimal access performance.

The Packed overrides this, compressing the data into the smallest storage, albeit with consequential reduced access performance.

A+
Jean
Commenter la réponse de jderf
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
0
Merci
J' ai pris connaissance de vos comentaires mais ça n' explique toujours pas le fait que l'instruction "packed" est indispensable .

Merci.


Composants Cindy pour Delphi
Faites une donation.
Commenter la réponse de cs_MAURICIO
Messages postés
192
Date d'inscription
mercredi 29 décembre 2004
Statut
Membre
Dernière intervention
2 octobre 2014
1
0
Merci
Tu as constaté cela sur quel système d'exploitation ? Ils sont pas tous redoutable dans la gestion de la mémoire

Le packed limite la taille pris par tes records et peut-être que tu mets pas l'OS dans le "rouge" ?

Jean
Commenter la réponse de jderf
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
0
Merci
C'est une question intéressante ... peut-être que tu n'a pas réglé le problème mais juste repoussé un peu plus loin.
ce qui me choque, c'est que monRecord contient 1 int : 4octets, et 1 string : 4 octets, donc a priori, ton record ne peut pas etre plus aligné que ca !
A priori, que monRecord soit "packed" ou pas, il devrait faire 8 octets
Commenter la réponse de Guillemouze
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
0
Merci
Je dirais comme Guillemouze.

Il faudrait vérifier les tailles mémoire des deux types de tableau.

Car, a priori, ton tableau packed devrait faire exactement la même taille mémoire que le même tableau non packed.
Et donc, si c'est bien le cas, les deux tableaux seraient 100% identiques !
Commenter la réponse de Caribensila
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
0
Merci
"C'est une question intéressante ... peut-être que tu n'a pas réglé le problème mais juste repoussé un peu plus loin"
- C' est exactement ce que je crains.


Pour info, je suis sous Delphi 2009 et mon record est beaucoup plus compliqué, ce n' était qu' un exemple!

a+


Composants Cindy pour Delphi
Faites une donation.
Commenter la réponse de cs_MAURICIO
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
0
Merci
Peut etre un probleme de lecture dans une zone invalide.
L'idéal serait de savoir l'erreur que tu as, et ce qui est fait dans la pile d'appel.
Souvent, les problèmes de ce style que j'ai rencontré, c'était a cause d'un accès hors limite. La plupart du temps, ca marchait, il y avait des trucs qui ressemblaient a ce que j'attendai a cet endroit de la memoire (genre la memoire n'a pas été reallouée depuis la derniere fois ou il y a eu un autre record semblable), ou une valeur qui faisait que je ne faisait pas de traitement (genre un nil à cet endroit).
De plus, il arrive souvent, dans ces circonstances et quand il y a des chaines, qu'il y ai un nil au niveau du pointeur correspondant à ta chaine, donc chaine vide, donc pas de problème; mais a partir du moment ou ce n'est pas nil, il le concidère comme un pointeur de chaine, qui est très spécial, et qui peut provoquer ces erreur.

As tu essayé de compiler et de tester avec verification des limites, des débordements dans les verification à l'execution dans les options de compilation ?
Commenter la réponse de Guillemouze
Messages postés
4200
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
2 janvier 2019
26
0
Merci
File ton code que je compile sur le miens de d2k9 :)
Je verrais bien si j'obtient le même comportement avec et sans Packed.

________________________________________________________
besoin de câbles audio, vidèo, informatique pas cher ?
Commenter la réponse de f0xi
Messages postés
420
Date d'inscription
samedi 17 mai 2003
Statut
Membre
Dernière intervention
6 mai 2019
15
0
Merci
Salut,

On pourrait avoir une description plus détaillée du record incriminé, avec le type des champs qui le composent ?
Commenter la réponse de korgis
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
0
Merci
Après une nuit de réflexion, j'me suis dit qu'un problème qui intervient aléatoirement, ca ne peut quasiment être qu'un pointeur dans l'espace (indice hors limite, ...). D'ailleurs, en remplaçant ton Array par une TList, tu aura un EIndexOutOfBounds là ou tu aurai eu un simple pointeur sur des données non valides avec l'array.
Commenter la réponse de Guillemouze
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
0
Merci
@Tous: voici plus d' info ...

C' est un problème qui surgit sur très peu de tifs (1 bug tous les 500 traitements, mais quand ça bugge sur un tif, ça le fait tout le temps).

Mon appli fait un OCR d' un tif à la fois et ensuite crée une liste des mots/expressions trouvées avec plusieurs informations comme la string, la position, type de valeur etc ...

Dans une 2ème phase (c' est ici que j' ai le problème), j' essaye de déterminer le téléphone, fax, montants HT, total ht, total ttc etc ...
Je garde ces infos de chaque élément dans un record, sachant que pour montant HT il s' agit d' un array of Record vu qu' il peut y avoir plusieurs valeurs.

Je vous comuniquerai le record en question plus tard.

a+

Composants Cindy pour Delphi
Faites une donation.
Commenter la réponse de cs_MAURICIO
Messages postés
2527
Date d'inscription
jeudi 15 janvier 2004
Statut
Membre
Dernière intervention
16 octobre 2019
13
0
Merci
@Mauricio
Sachant qu'un array peut aussi être packed ou non, dis-nous bien, stp, ce qui est packed et non packed dans ton record à tiroirs.
Commenter la réponse de Caribensila
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
0
Merci
[quote=mauricio]Je garde ces infos de chaque élément dans un record, sachant que pour montant HT il s' agit d' un array of Record vu qu' il peut y avoir plusieurs valeurs.
/quote
Attention, si tu modifies la taille de ton tableau general :
SetLength(ArrayTifs, nbTifs)

alors le contenu de ArrayTifs[i] n'est pas initialisé, il peut y avoir n'importe quoi dedans.
Et en l'occurence, admettons que monRec = ArrayTifs[i], monRec.TabHT doit être initialisé(à nil ou SetLength(x)) avant d'etre accedé. Par exemple, si tu fais
SetLengh(monRec.tabHT, Length(monRec.tabHT)+1)

tu risque l'erreur si il n'y avait pas des 0 sur l'emplacement mémoire de tabHT.
L'idéal etant de faire un truc du genre
type
  TMonRec = record
   x: integer;
   tabHt: TRealDynArray;
   ...
  end;

const 
  DefaultRec: TMonRec = (); // tout à nil

var
  MonTab: array of TMonRec;

SetLength(MonTab, 20);
for i := 0 to 19 do
  MonTab[i] := DefaultRec;
//ou peut etre FillChar / ZeroMem, mais dépend de l'alignement de ton tableau
Commenter la réponse de Guillemouze
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
0
Merci
Me revoici avec cette fois l' unité en question :

unit Unite_coherence;

interface

uses cyDocER, cyDERUtils, Math;

type
  recValeurs = packed record
    Valeur: Extended;
    ExpressionIndex: Integer;
  end;

  recSyntheseFloat = packed record
    AssociatedExpressionKeywordIndex: Integer;
    ExpressionIndex: Integer;
    Valeur: Extended;

    // Dans le cas oú l' on a plusieurs valeurs :
    Valeurs: Array of recValeurs;
    LengthValeurs: Integer;
  end;

  RecSyntheseDoc = packed record         // "packed" evite erreur de manipulation de la taille des arrays ...
    NumFacture: String;
    DateFacture: TDate;
    TVAIntracom: String;
    NumSiret: String;
    Telephone: String;
    Fax: String;
    EMail: String;
    Website: String;
    NumClient: String;

    NumFacture_ExpressionIndex: Integer;
    DateFacture_ExpressionIndex: Integer;
    TVAIntracom_ExpressionIndex: Integer;
    NumSiret_ExpressionIndex: Integer;
    Telephone_ExpressionIndex: Integer;
    Fax_ExpressionIndex: Integer;
    EMail_ExpressionIndex: Integer;
    Website_ExpressionIndex: Integer;
    NumClient_ExpressionIndex: Integer;

    Somme_MontantsTVA: Array of recSyntheseFloat;
    TauxTVA: Array of recSyntheseFloat;
    TotalTVA: Array of recSyntheseFloat;

    Somme_MontantsHT: Array of recSyntheseFloat;
    TotalHT: Array of recSyntheseFloat;
    RemiseHT: Array of recSyntheseFloat;
    FraisDePort: Array of recSyntheseFloat;  // Hors taxe!  (Somme montants HT + frais de port = Total hors taxe)

    Somme_MontantsTTC: Array of recSyntheseFloat;
    TotalTTC: Array of recSyntheseFloat;
    DebitAnterieur: Array of recSyntheseFloat;
    NetAPayer: Array of recSyntheseFloat;

    // Variable de gestion de la taille des tableaux :
    LengthSomme_MontantsTVA: Integer;
    LengthTauxTVA: Integer;
    LengthTotalTVA: Integer;

    LengthSomme_MontantsHT: Integer;
    LengthTotalHT: Integer;
    LengthRemiseHT: Integer;
    LengthFraisDePort: Integer;

    LengthSomme_MontantsTTC: Integer;
    LengthTotalTTC: Integer;
    LengthDebitAnterieur: Integer;
    LengthNetAPayer: Integer;

    // Résultat de la cohérence :
    IndexRsltSomme_MontantsTVA: Integer;
    IndexRsltTauxTVA: Integer;
    IndexRsltTotalTVA: Integer;

    IndexRsltSomme_MontantsHT: Integer;
    IndexRsltTotalHT: Integer;
    IndexRsltRemiseHT: Integer;
    IndexRsltFraisDePort: Integer;

    IndexRsltSomme_MontantsTTC: Integer;
    IndexRsltTotalTTC: Integer;
    IndexRsltDebitAnterieur: Integer;
    IndexRsltNetAPayer: Integer;
  end;

const
  cOCRElementNumFacture     =   1;
  cOCRElementDate           =   2;
  cOCRElementTVAIntracom    =   3;
  cOCRElementNumSiret       =   4;
  cOCRElementTelephone      =   5;
  cOCRElementFax            =   6;
  cOCRElementEMail          =   7;
  cOCRElementWebsite        =   8;
  cOCRElementNomFournisseur =   9;                        // Seulement par patron !
  cOCRElementNumClient      =  10;

  cOCRElementNumerique      = 100;
  cOCRElementNetAPayer      = 101;
  cOCRElementMontantTTC     = 102;   // Plusieurs lignes
  cOCRElementTotalTTC       = 103;
  cOCRElementDebitAnterieur = 104;

  cOCRElementMontantHT      = 201;   // Plusieurs lignes
  cOCRElementTotalHT        = 202;
  cOCRElementRemiseHT       = 203;

  cOCRElementTauxTVA        = 301;   // Plusieurs lignes
  cOCRElementMontantTVA     = 302;   // Plusieurs lignes
  cOCRElementTotalTVA       = 303;
  cOCRElementFraisDePort    = 401;

  cOCRElementARejeter       = 999;  // Mots clés à rejeter


function ValeursEgales(Valeur1, Valeur2: Extended): Boolean;
procedure Initialise_SyntheseDoc(var aRecSyntheseDoc: RecSyntheseDoc);
function Localiser_recSyntheseFloat(TableauRecSyntheseFloat: Array of recSyntheseFloat; AssociatedExpressionKeywordIndex: Integer): Integer;
procedure Executer_CoherenceDoc(var aRecSyntheseDoc: RecSyntheseDoc; UnDocument: TcyDocER);

implementation

uses f_prin;

function Arrondir(Valor: Double; Decimais: Integer): Double;
var Negativo: Boolean;
    ParteDec, Precisao_Inv : Double;
begin
  // Exemplo com Valor 130.144999 e decimais 2 :
  Negativo := Valor < 0;

  if Negativo
  then Valor := Abs(Valor);

  Precisao_Inv := Power(10, Decimais);
  // Precisao_Inv = 100 ...

  RESULT := Int(Valor);
  // RESULT = 130 ...

  ParteDec   := (Valor - RESULT) * Precisao_Inv;
  // x = 14.4999 ...

  RESULT := RESULT + (Int(ParteDec) / Precisao_Inv); // Recortar os digitos decimais que queremos ...
  // RESULT = 130.14 ...

  // Ver se temos que arredondar para cima :
  if ParteDec - Int(ParteDec) >0.4999999   // Quando x 0.5, o delphi dá-lhe outro valor de tipo 0.4999999999 ...
  then RESULT := RESULT + (1 / Precisao_Inv);

  if Negativo
  then RESULT := (-1) * RESULT;
end;

function ValeursEgales(Valeur1, Valeur2: Extended): Boolean;
begin
  Result := Abs(Valeur1-Valeur2) <= 0.01;
end;

procedure Initialise_SyntheseDoc(var aRecSyntheseDoc: RecSyntheseDoc);
begin
  aRecSyntheseDoc.NumFacture     := '';
  aRecSyntheseDoc.DateFacture    :=  0;
  aRecSyntheseDoc.TVAIntracom    := '';
  aRecSyntheseDoc.NumSiret       := '';
  aRecSyntheseDoc.Telephone      := '';
  aRecSyntheseDoc.Fax            := '';
  aRecSyntheseDoc.EMail          := '';
  aRecSyntheseDoc.Website        := '';
  aRecSyntheseDoc.NumClient      := '';

  aRecSyntheseDoc.NumFacture_ExpressionIndex     :=  -1;
  aRecSyntheseDoc.DateFacture_ExpressionIndex    :=  -1;
  aRecSyntheseDoc.TVAIntracom_ExpressionIndex    :=  -1;
  aRecSyntheseDoc.NumSiret_ExpressionIndex       :=  -1;
  aRecSyntheseDoc.Telephone_ExpressionIndex      :=  -1;
  aRecSyntheseDoc.Fax_ExpressionIndex            :=  -1;
  aRecSyntheseDoc.EMail_ExpressionIndex          :=  -1;
  aRecSyntheseDoc.Website_ExpressionIndex        :=  -1;
  aRecSyntheseDoc.NumClient_ExpressionIndex      :=  -1;

  // Taille des tableaux :
  SetLength(aRecSyntheseDoc.Somme_MontantsTVA, 0);
  SetLength(aRecSyntheseDoc.TauxTVA, 0);
  SetLength(aRecSyntheseDoc.TotalTVA, 0);

  SetLength(aRecSyntheseDoc.Somme_MontantsHT, 0);
  SetLength(aRecSyntheseDoc.TotalHT, 0);
  SetLength(aRecSyntheseDoc.RemiseHT, 0);

  SetLength(aRecSyntheseDoc.Somme_MontantsTTC, 0);
  SetLength(aRecSyntheseDoc.TotalTTC, 0);
  SetLength(aRecSyntheseDoc.DebitAnterieur, 0);
  SetLength(aRecSyntheseDoc.NetAPayer, 0);

  // Variables des tableaux :
  aRecSyntheseDoc.LengthSomme_MontantsTVA := 0;
  aRecSyntheseDoc.LengthTauxTVA := 0;
  aRecSyntheseDoc.LengthTotalTVA := 0;

  aRecSyntheseDoc.LengthSomme_MontantsHT := 0;
  aRecSyntheseDoc.LengthTotalHT := 0;
  aRecSyntheseDoc.LengthRemiseHT := 0;
  aRecSyntheseDoc.LengthFraisDePort := 0;

  aRecSyntheseDoc.LengthSomme_MontantsTTC := 0;
  aRecSyntheseDoc.LengthTotalTTC := 0;
  aRecSyntheseDoc.LengthDebitAnterieur := 0;
  aRecSyntheseDoc.LengthNetAPayer := 0;

  // Résultat de la cohérence :
  aRecSyntheseDoc.IndexRsltSomme_MontantsTVA := -1;
  aRecSyntheseDoc.IndexRsltTauxTVA := -1;
  aRecSyntheseDoc.IndexRsltTotalTVA := -1;

  aRecSyntheseDoc.IndexRsltSomme_MontantsHT := -1;
  aRecSyntheseDoc.IndexRsltTotalHT := -1;
  aRecSyntheseDoc.IndexRsltRemiseHT := -1;
  aRecSyntheseDoc.IndexRsltFraisDePort := -1;

  aRecSyntheseDoc.IndexRsltSomme_MontantsTTC := -1;
  aRecSyntheseDoc.IndexRsltTotalTTC := -1;
  aRecSyntheseDoc.IndexRsltDebitAnterieur := -1;
  aRecSyntheseDoc.IndexRsltNetAPayer := -1;
end;

function Localiser_recSyntheseFloat(TableauRecSyntheseFloat: Array of recSyntheseFloat; AssociatedExpressionKeywordIndex: Integer): Integer;
var i: Integer;
begin
  Result := -1;
  for i := 0 to length(TableauRecSyntheseFloat) - 1 do
    if TableauRecSyntheseFloat[i].AssociatedExpressionKeywordIndex = AssociatedExpressionKeywordIndex then
    begin
      Result := i;
      Break;
    end;
end;

procedure Executer_CoherenceDoc(var aRecSyntheseDoc: RecSyntheseDoc; UnDocument: TcyDocER);

      // Total TTC = Total HT + Total TVA :
      // Total TTC = Total HT + Somme montants TVA :
      // Total TTC = Somme montants HT + Total TVA :
      // Total TTC = Somme montants HT + Somme montants TVA :
      function Valider_TotalTTC(ValeurTotalTTC: Extended): Boolean;
      var tht, ttva, mht, mtva: Integer;
      begin
        Result := false;
        if ValeurTotalTTC = 0 then Exit;

        for tht := 0 to aRecSyntheseDoc.LengthTotalHT - 1 do
        begin
          for ttva := 0 to aRecSyntheseDoc.LengthTotalTVA - 1 do
            if ValeursEgales(ValeurTotalTTC, aRecSyntheseDoc.TotalHT[tht].Valeur + aRecSyntheseDoc.TotalTVA[ttva].Valeur) then
            begin
              Result := True;
              aRecSyntheseDoc.IndexRsltTotalHT := tht;
              aRecSyntheseDoc.IndexRsltTotalTVA := ttva;
              Exit;
            end;

          for mtva := 0 to aRecSyntheseDoc.LengthSomme_MontantsTVA - 1 do
            if ValeursEgales(ValeurTotalTTC, aRecSyntheseDoc.TotalHT[tht].Valeur + aRecSyntheseDoc.Somme_MontantsTVA[mtva].Valeur) then
            begin
              Result := True;
              aRecSyntheseDoc.IndexRsltTotalHT := tht;
              aRecSyntheseDoc.IndexRsltSomme_MontantsTVA := mtva;
              Exit;
            end;
        end;

        for mht := 0 to aRecSyntheseDoc.LengthSomme_MontantsHT - 1 do
        begin
          for ttva := 0 to aRecSyntheseDoc.LengthTotalTVA - 1 do
            if ValeursEgales(ValeurTotalTTC, aRecSyntheseDoc.Somme_MontantsHT[mht].Valeur + aRecSyntheseDoc.TotalTVA[ttva].Valeur) then
            begin
              Result := True;
              aRecSyntheseDoc.IndexRsltSomme_MontantsHT := mht;
              aRecSyntheseDoc.IndexRsltTotalTVA := ttva;
              Exit;
            end;

          for mtva := 0 to aRecSyntheseDoc.LengthSomme_MontantsTVA - 1 do
            if ValeursEgales(ValeurTotalTTC, aRecSyntheseDoc.Somme_MontantsHT[mht].Valeur + aRecSyntheseDoc.Somme_MontantsTVA[mtva].Valeur) then
            begin
              Result := True;
              aRecSyntheseDoc.IndexRsltSomme_MontantsHT := mht;
              aRecSyntheseDoc.IndexRsltSomme_MontantsTVA := mtva;
              Exit;
            end;
        end;
      end;

      function Valider_TauxTVA(IndexMontantsHT, IndexMontantsTVA, IndexTauxTVA: Integer): Boolean;
      var
        i, m, NbMontants: Integer;
      begin
        Result := true;
        NbMontants := aRecSyntheseDoc.Somme_MontantsHT[IndexMontantsHT].LengthValeurs;

        if aRecSyntheseDoc.Somme_MontantsTVA[IndexMontantsTVA].LengthValeurs <> NbMontants then
        begin
          Result := false;
          Exit;
        end;

        if IndexTauxTVA <> -1 then
          if aRecSyntheseDoc.TauxTVA[IndexTauxTVA].LengthValeurs < NbMontants then
          begin
            Result := false;
            Exit;
          end;

        // Vérifier si le taux est ok pour chaque montant HT et chaque montant TVA :
        if IndexTauxTVA = -1 then
        begin
          Result := false;

          for i := 0 to aRecSyntheseDoc.LengthTauxTVA - 1 do
            if Valider_TauxTVA(IndexMontantsHT, IndexMontantsTVA, i) then
            begin
              Result := true;
              aRecSyntheseDoc.IndexRsltTauxTVA := i;
            end;
        end
        else
          for m := 0 to NbMontants-1 do
              if not ValeursEgales(aRecSyntheseDoc.Somme_MontantsHT[IndexMontantsHT].Valeurs[m].Valeur * (aRecSyntheseDoc.TauxTVA[IndexTauxTVA].Valeurs[m].Valeur/100),
                                   aRecSyntheseDoc.Somme_MontantsTVA[IndexMontantsTVA].Valeurs[m].Valeur) then
                Result := false;
      end;

var
  s, s2, n, t, t2, t3, f, d, aExpressionIndex, aAssociatedExpressionKeywordIndex: Integer;
  ValeurMax, TmpExtended: Extended;
  UneCoherenceTrouvee: Boolean;
  Retours: Integer;
  I: Integer;
  _TotalHT, _TotalTVA, _TotalTTC: Extended;
label
  RelancerCoherence;

begin
  // *** Initialisations *** //
  Retours := 0;

  // Ajouter 0 aux frais de port :
  Inc(aRecSyntheseDoc.LengthFraisDePort);
  Setlength(aRecSyntheseDoc.FraisDePort, aRecSyntheseDoc.LengthFraisDePort);
  aRecSyntheseDoc.FraisDePort[aRecSyntheseDoc.LengthFraisDePort-1].Valeur := 0;

  // Ajouter 0 aux remises HT :
  Inc(aRecSyntheseDoc.LengthRemiseHT);
  Setlength(aRecSyntheseDoc.RemiseHT, aRecSyntheseDoc.LengthRemiseHT);
  aRecSyntheseDoc.RemiseHT[aRecSyntheseDoc.LengthRemiseHT-1].Valeur := 0;

  // Ajouter 0 au débit antérieur :
  Inc(aRecSyntheseDoc.LengthDebitAnterieur);
  Setlength(aRecSyntheseDoc.DebitAnterieur, aRecSyntheseDoc.LengthDebitAnterieur);
  aRecSyntheseDoc.DebitAnterieur[aRecSyntheseDoc.LengthDebitAnterieur-1].Valeur := 0;

  // *** 18/10/2012 - AFI_656053.tif - Impossible de faire le SetLength dans l' Array aRecSyntheseDoc.TotalTVA depuis ici ...

  // *** Si les taux sont trouvés "manuellement" *** //
  for t := 0 to aRecSyntheseDoc.LengthTauxTVA-1 do
    if aRecSyntheseDoc.TauxTVA[t].AssociatedExpressionKeywordIndex = -1 then
      aRecSyntheseDoc.IndexRsltTauxTVA := t;

  // *** Cohérences entre les éléments somme et totaux *** //

  RelancerCoherence:
  UneCoherenceTrouvee := false;

  // Chercher une cohérence entre les montants TTC et le Total TTC :
  if (aRecSyntheseDoc.IndexRsltSomme_MontantsTTC -1) or (aRecSyntheseDoc.IndexRsltTotalTTC -1) then
    for s := 0 to aRecSyntheseDoc.LengthSomme_MontantsTTC - 1 do
      if (aRecSyntheseDoc.IndexRsltSomme_MontantsTTC -1) or (aRecSyntheseDoc.IndexRsltSomme_MontantsTTC s) then
        if aRecSyntheseDoc.Somme_MontantsTTC[s].Valeur <> 0 then
          for t := 0 to aRecSyntheseDoc.LengthTotalTTC - 1 do
            if (aRecSyntheseDoc.IndexRsltTotalTTC -1) or (aRecSyntheseDoc.IndexRsltTotalTTC t) then
              if ValeursEgales(aRecSyntheseDoc.Somme_MontantsTTC[s].Valeur, aRecSyntheseDoc.TotalTTC[t].Valeur) then
              begin
                if aRecSyntheseDoc.IndexRsltSomme_MontantsTTC <> s then
                begin
                  aRecSyntheseDoc.IndexRsltSomme_MontantsTTC := s;
                  UneCoherenceTrouvee := true;
                end;

                if aRecSyntheseDoc.IndexRsltTotalTTC <> t then
                begin
                  aRecSyntheseDoc.IndexRsltTotalTTC := t;
                  UneCoherenceTrouvee := true;
                end;
              end;

  // Chercher une cohérence entre les montants HT et le Total HT :
  if (aRecSyntheseDoc.IndexRsltSomme_MontantsHT -1) or (aRecSyntheseDoc.IndexRsltTotalHT -1) then
    for s := 0 to aRecSyntheseDoc.LengthSomme_MontantsHT - 1 do
      if (aRecSyntheseDoc.IndexRsltSomme_MontantsHT -1) or (aRecSyntheseDoc.IndexRsltSomme_MontantsHT s) then
        if aRecSyntheseDoc.Somme_MontantsHT[s].Valeur <> 0 then
          for t := 0 to aRecSyntheseDoc.LengthTotalHT - 1 do
            if (aRecSyntheseDoc.IndexRsltTotalHT -1) or (aRecSyntheseDoc.IndexRsltTotalHT t) then
              for f := 0 to aRecSyntheseDoc.LengthFraisDePort - 1 do
                if (aRecSyntheseDoc.IndexRsltFraisDePort -1) or (aRecSyntheseDoc.IndexRsltFraisDePort f) then
                  if ValeursEgales(aRecSyntheseDoc.Somme_MontantsHT[s].Valeur + aRecSyntheseDoc.FraisDePort[f].Valeur, aRecSyntheseDoc.TotalHT[t].Valeur) then
                  begin
                    if aRecSyntheseDoc.IndexRsltSomme_MontantsHT <> s then
                    begin
                      aRecSyntheseDoc.IndexRsltSomme_MontantsHT := s;
                      UneCoherenceTrouvee := true;
                    end;

                    if aRecSyntheseDoc.IndexRsltTotalHT <> t then
                    begin
                      aRecSyntheseDoc.IndexRsltTotalHT := t;
                      UneCoherenceTrouvee := true;
                    end;

                    if aRecSyntheseDoc.IndexRsltFraisDePort <> f then
                    begin
                      aRecSyntheseDoc.IndexRsltFraisDePort := f;
                      UneCoherenceTrouvee := true;
                    end;
                  end;

  // Chercher une cohérence entre les montants HT, Montants TVA :
  if (aRecSyntheseDoc.IndexRsltSomme_MontantsHT -1) or (aRecSyntheseDoc.IndexRsltSomme_MontantsTVA -1) then
    for s := 0 to aRecSyntheseDoc.LengthSomme_MontantsHT - 1 do
      if (aRecSyntheseDoc.IndexRsltSomme_MontantsHT -1) or (aRecSyntheseDoc.IndexRsltSomme_MontantsHT s) then
        if aRecSyntheseDoc.Somme_MontantsHT[s].Valeur <> 0 then
          for s2 := 0 to aRecSyntheseDoc.LengthSomme_MontantsTVA - 1 do
            if (aRecSyntheseDoc.IndexRsltSomme_MontantsTVA -1) or (aRecSyntheseDoc.IndexRsltSomme_MontantsTVA s2) then
              if Valider_TauxTVA(s, s2, aRecSyntheseDoc.IndexRsltTauxTVA) then  // Compare pour chaque montant HT et chaque montant TVA si le taux est ok
              begin
                aRecSyntheseDoc.IndexRsltSomme_MontantsHT := s;
                aRecSyntheseDoc.IndexRsltSomme_MontantsTVA := s2;
                UneCoherenceTrouvee := true;
              end;

  // Total TVA = Total TTC - Total HT:
  if (aRecSyntheseDoc.IndexRsltTotalTVA = -1) and (aRecSyntheseDoc.IndexRsltTotalHT <> -1) and (aRecSyntheseDoc.IndexRsltTotalTTC <> -1) then
    for t := 0 to aRecSyntheseDoc.LengthTotalTVA - 1 do
      if ValeursEgales(aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.IndexRsltTotalTTC].Valeur
                        - aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.IndexRsltTotalHT].Valeur, aRecSyntheseDoc.TotalTVA[t].Valeur) then
      begin
        aRecSyntheseDoc.IndexRsltTotalTVA := t;
        UneCoherenceTrouvee := true;
      end;

  // Total HT = Total TTC - Total TVA:
  if (aRecSyntheseDoc.IndexRsltTotalHT = -1) and (aRecSyntheseDoc.IndexRsltTotalTVA <> -1) and (aRecSyntheseDoc.IndexRsltTotalTTC <> -1) then
    for t := 0 to aRecSyntheseDoc.LengthTotalHT - 1 do
      if ValeursEgales(aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.IndexRsltTotalTTC].Valeur
                        - aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.IndexRsltTotalTVA].Valeur, aRecSyntheseDoc.TotalHT[t].Valeur) then
      begin
        aRecSyntheseDoc.IndexRsltTotalHT := t;
        UneCoherenceTrouvee := true;
      end;

  // *** Calcul du Total TTC *** //

  // Total TTC = Total HT (ou somme montants HT) + Total TVA (ou somme montants TVA) :
  if aRecSyntheseDoc.IndexRsltTotalTTC = -1 then
    for t := 0 to aRecSyntheseDoc.LengthTotalTTC - 1 do
//      for f := 0 to aRecSyntheseDoc.LengthFraisDePort - 1 do
        if Valider_TotalTTC(aRecSyntheseDoc.TotalTTC[t].Valeur{ - aRecSyntheseDoc.FraisDePort[f].Valeur}) then
        begin
          UneCoherenceTrouvee := True;
          aRecSyntheseDoc.IndexRsltTotalTTC := t;
//          aRecSyntheseDoc.IndexRsltFraisDePort := f;
        end;

  // *** Calcul du Net à payer *** //
  // Net à payer = Total TTC  + Debit anterieur
  if aRecSyntheseDoc.IndexRsltTotalTTC = -1 then
  begin
    // Chercher une cohérence entre les montants TTC et le net à payer :
    if aRecSyntheseDoc.IndexRsltSomme_MontantsTTC = -1 then
      for s := 0 to aRecSyntheseDoc.LengthSomme_MontantsTTC - 1 do
        if aRecSyntheseDoc.Somme_MontantsTTC[s].Valeur <> 0 then
          for d := 0 to aRecSyntheseDoc.LengthDebitAnterieur - 1 do
            for n := 0 to aRecSyntheseDoc.LengthNetAPayer - 1 do
              if ValeursEgales(aRecSyntheseDoc.Somme_MontantsTTC[s].Valeur + aRecSyntheseDoc.DebitAnterieur[d].Valeur, aRecSyntheseDoc.NetAPayer[n].Valeur) then
              begin
                UneCoherenceTrouvee := True;
                aRecSyntheseDoc.IndexRsltSomme_MontantsTTC := s;
                aRecSyntheseDoc.IndexRsltDebitAnterieur := d;
                aRecSyntheseDoc.IndexRsltNetAPayer := n;
              end;

    // Net à payer = Total HT (ou somme montants HT) + Total TVA (ou somme montants TVA) + Debit anterieur
    if aRecSyntheseDoc.IndexRsltNetAPayer = -1 then
      for n := 0 to aRecSyntheseDoc.LengthNetAPayer - 1 do
        for d := 0 to aRecSyntheseDoc.LengthDebitAnterieur - 1 do
//          for f := 0 to aRecSyntheseDoc.LengthFraisDePort - 1 do
            if Valider_TotalTTC(aRecSyntheseDoc.NetAPayer[n].Valeur {- aRecSyntheseDoc.FraisDePort[f].Valeur} + aRecSyntheseDoc.DebitAnterieur[d].Valeur) then
            begin
              UneCoherenceTrouvee := True;
              aRecSyntheseDoc.IndexRsltNetAPayer := n;
              aRecSyntheseDoc.IndexRsltDebitAnterieur := d;
//              aRecSyntheseDoc.IndexRsltFraisDePort := f;
            end;

{   // On ne peut pas faire de cohérnce entre 2 éléments qui ont presque toujours la même valeur car ça les valide même si les valeurs mal OCRIsées
    // Si on a ni le Total TTC ni le Net à payer :
    if aRecSyntheseDoc.IndexRsltNetAPayer = -1 then
      if aRecSyntheseDoc.LengthNetAPayer <> 0 then
      begin
        if aRecSyntheseDoc.LengthTotalTTC <> 0 then
        begin
          // Chercher une cohérence entre le total TTC  et le net à payer :
          for t := 0 to aRecSyntheseDoc.LengthTotalTTC - 1 do
            for n := 0 to aRecSyntheseDoc.LengthNetAPayer - 1 do
              for d := 0 to aRecSyntheseDoc.LengthDebitAnterieur - 1 do
//                for f := 0 to aRecSyntheseDoc.LengthFraisDePort - 1 do
//                if ValeursEgales(aRecSyntheseDoc.NetAPayer[n].Valeur, aRecSyntheseDoc.TotalTTC[t].Valeur  + aRecSyntheseDoc.FraisDePort[f].Valeur + aRecSyntheseDoc.DebitAnterieur[d].Valeur) then
                  if ValeursEgales(aRecSyntheseDoc.NetAPayer[n].Valeur, aRecSyntheseDoc.TotalTTC[t].Valeur + aRecSyntheseDoc.DebitAnterieur[d].Valeur) then
                  begin
                    UneCoherenceTrouvee := True;
                    aRecSyntheseDoc.IndexRsltTotalTTC := t;
                    aRecSyntheseDoc.IndexRsltNetAPayer := n;
                    aRecSyntheseDoc.IndexRsltDebitAnterieur := d;
//                    aRecSyntheseDoc.IndexRsltFraisDePort := f;
                  end;
        end
        else
          if aRecSyntheseDoc.LengthNetAPayer <> 0 then
          begin
            UneCoherenceTrouvee := True;
            aRecSyntheseDoc.IndexRsltNetAPayer := aRecSyntheseDoc.LengthNetAPayer - 1;
          end;
      end
      else
        if aRecSyntheseDoc.LengthTotalTTC <> 0 then
        begin
          UneCoherenceTrouvee := True;
          aRecSyntheseDoc.IndexRsltTotalTTC := aRecSyntheseDoc.LengthTotalTTC - 1;
        end;     }
  end
  else begin
    // On a le total TTC et au moins une autre valeur, chercher une cohérence entre le total TTC et le net à payer :
    if (aRecSyntheseDoc.IndexRsltNetAPayer = -1) and ((aRecSyntheseDoc.IndexRsltTotalHT <> -1) or (aRecSyntheseDoc.IndexRsltTotalTVA <> -1)) then
      for n := 0 to aRecSyntheseDoc.LengthNetAPayer - 1 do
        for d := 0 to aRecSyntheseDoc.LengthDebitAnterieur - 1 do
  //        for f := 0 to aRecSyntheseDoc.LengthFraisDePort - 1 do
            if ValeursEgales(aRecSyntheseDoc.NetAPayer[n].Valeur, aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.IndexRsltTotalTTC].Valeur {+ aRecSyntheseDoc.FraisDePort[f].Valeur} + aRecSyntheseDoc.DebitAnterieur[d].Valeur) then
            begin
              if (aRecSyntheseDoc.IndexRsltNetAPayer -1) or (aRecSyntheseDoc.IndexRsltDebitAnterieur -1) {or (aRecSyntheseDoc.IndexRsltFraisDePort = -1)} then
                UneCoherenceTrouvee := True;

              aRecSyntheseDoc.IndexRsltNetAPayer := n;
              aRecSyntheseDoc.IndexRsltDebitAnterieur := d;
  //            aRecSyntheseDoc.IndexRsltFraisDePort := f;
            end;
  end;

  // Taux de TVA depuis le total HT et Total Montant TVA :
  if aRecSyntheseDoc.IndexRsltTauxTVA = -1 then
    if (aRecSyntheseDoc.IndexRsltSomme_MontantsTTC -1) and (aRecSyntheseDoc.IndexRsltSomme_MontantsTVA -1) then
      if (aRecSyntheseDoc.IndexRsltTotalHT <> -1) and (aRecSyntheseDoc.IndexRsltTotalTVA <> -1) then
      begin
        for t := 0 to aRecSyntheseDoc.LengthTauxTVA-1 do
          if aRecSyntheseDoc.TauxTVA[t].LengthValeurs = 1 then
            if ValeursEgales(aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur * aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.IndexRsltTotalHT].Valeur / 100,
                               aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.IndexRsltTotalTVA].Valeur) then
            begin
              UneCoherenceTrouvee := True;
              aRecSyntheseDoc.IndexRsltTauxTVA := t;
            end;

        // Calculer le taux :
        if aRecSyntheseDoc.IndexRsltTauxTVA = -1 then
        begin
          if FrmPrin.Pays_TauxTVA1 <> 0 then
            if ValeursEgales(FrmPrin.Pays_TauxTVA1 * aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.IndexRsltTotalHT].Valeur / 100, aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.IndexRsltTotalTVA].Valeur) then
            begin
              UneCoherenceTrouvee := True;
              t := aRecSyntheseDoc.LengthTauxTVA;
              Inc(aRecSyntheseDoc.LengthTauxTVA);
              SetLength(aRecSyntheseDoc.TauxTVA, aRecSyntheseDoc.LengthTauxTVA);

              aRecSyntheseDoc.TauxTVA[t].AssociatedExpressionKeywordIndex := -1;
              aRecSyntheseDoc.TauxTVA[t].ExpressionIndex := -1;
              aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].LengthValeurs := 1;
              SetLength(aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].Valeurs, 1);
              aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].Valeurs[0].Valeur := FrmPrin.Pays_TauxTVA1;

              aRecSyntheseDoc.IndexRsltTauxTVA := t;
            end;

          if FrmPrin.Pays_TauxTVA2 <> 0 then
            if ValeursEgales(FrmPrin.Pays_TauxTVA2 * aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.IndexRsltTotalHT].Valeur / 100, aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.IndexRsltTotalTVA].Valeur) then
            begin
              UneCoherenceTrouvee := True;
              t := aRecSyntheseDoc.LengthTauxTVA;
              Inc(aRecSyntheseDoc.LengthTauxTVA);
              SetLength(aRecSyntheseDoc.TauxTVA, aRecSyntheseDoc.LengthTauxTVA);

              aRecSyntheseDoc.TauxTVA[t].AssociatedExpressionKeywordIndex := -1;
              aRecSyntheseDoc.TauxTVA[t].ExpressionIndex := -1;
              aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].LengthValeurs := 1;
              SetLength(aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].Valeurs, 1);
              aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].Valeurs[0].Valeur := FrmPrin.Pays_TauxTVA2;

              aRecSyntheseDoc.IndexRsltTauxTVA := t;
            end;

          if FrmPrin.Pays_TauxTVA3 <> 0 then
            if ValeursEgales(FrmPrin.Pays_TauxTVA3 * aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.IndexRsltTotalHT].Valeur / 100, aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.IndexRsltTotalTVA].Valeur) then
            begin
              UneCoherenceTrouvee := True;
              t := aRecSyntheseDoc.LengthTauxTVA;
              Inc(aRecSyntheseDoc.LengthTauxTVA);
              SetLength(aRecSyntheseDoc.TauxTVA, aRecSyntheseDoc.LengthTauxTVA);

              aRecSyntheseDoc.TauxTVA[t].AssociatedExpressionKeywordIndex := -1;
              aRecSyntheseDoc.TauxTVA[t].ExpressionIndex := -1;
              aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].LengthValeurs := 1;
              SetLength(aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].Valeurs, 1);
              aRecSyntheseDoc.TauxTVA[aRecSyntheseDoc.LengthTauxTVA-1].Valeurs[0].Valeur := FrmPrin.Pays_TauxTVA3;

              aRecSyntheseDoc.IndexRsltTauxTVA := t;
            end;

        end;
      end;

  // 26/05/2012 - Chercher une cohérence entre 3 valeurs : Total HT, Total TVA et Total TTC
  if (aRecSyntheseDoc.IndexRsltTotalTTC -1) or (aRecSyntheseDoc.IndexRsltTotalHT -1) or (aRecSyntheseDoc.IndexRsltTotalTVA = -1) then
    for t3 := 0 to aRecSyntheseDoc.LengthTotalTTC-1 do
      if (aRecSyntheseDoc.IndexRsltTotalTTC t3) or (aRecSyntheseDoc.IndexRsltTotalTTC -1) then
        for t2 := 0 to aRecSyntheseDoc.LengthTotalHT-1 do
          if (aRecSyntheseDoc.IndexRsltTotalHT t2) or (aRecSyntheseDoc.IndexRsltTotalHT -1) then
            for t := 0 to aRecSyntheseDoc.LengthTotalTVA-1 do
              if (aRecSyntheseDoc.IndexRsltTotalTVA t) or (aRecSyntheseDoc.IndexRsltTotalTVA -1) then
                if ValeursEgales(aRecSyntheseDoc.TotalTTC[t3].Valeur, aRecSyntheseDoc.TotalHT[t2].Valeur + aRecSyntheseDoc.TotalTVA[t].Valeur) then
                begin
                  UneCoherenceTrouvee := True;
                  aRecSyntheseDoc.IndexRsltTotalTTC := t3;
                  aRecSyntheseDoc.IndexRsltTotalHT  := t2;
                  aRecSyntheseDoc.IndexRsltTotalTVA := t;
                end;


  // *** Cohérences par déduction et recherche de nouvelles valeurs *** //

  // 27/05/2012 - Copier le net à payer vers le TotalTTC :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.LengthTotalTTC 0) and (aRecSyntheseDoc.LengthNetAPayer 1) then
    begin
      UneCoherenceTrouvee := true;
      aRecSyntheseDoc.LengthTotalTTC := 1;
      SetLength(aRecSyntheseDoc.TotalTTC, 1);
      aRecSyntheseDoc.TotalTTC[0] := aRecSyntheseDoc.NetAPayer[0];
    end;

  // 26/05/2012 - Ajouter total HT grâce au taux (même si tableau non vide, car la valeur a pu être mal OCRisée) et valider avec Total TTC, taux TVA et valeur de la TVA:
  if not UneCoherenceTrouvee then
    try
      if (aRecSyntheseDoc.IndexRsltTotalTTC -1) or (aRecSyntheseDoc.IndexRsltTauxTVA -1) or (aRecSyntheseDoc.IndexRsltTotalTVA = -1) then
        for t3 := 0 to aRecSyntheseDoc.LengthTotalTTC-1 do
          if (aRecSyntheseDoc.IndexRsltTotalTTC t3) or (aRecSyntheseDoc.IndexRsltTotalTTC -1) then
            for t := 0 to aRecSyntheseDoc.LengthTauxTVA-1 do
              if ((t aRecSyntheseDoc.IndexRsltTauxTVA) or (aRecSyntheseDoc.IndexRsltTauxTVA -1))
                and (aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur > 0) and (aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur <> 100) then
              begin
                _TotalHT := Arrondir( aRecSyntheseDoc.TotalTTC[t3].Valeur / (1+(aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur/100)), 2 );

                // Voir s' il y a une cohérence entre le TotalHT et le total TVA :
                for t2 := 0 to aRecSyntheseDoc.LengthTotalTVA-1 do
                  if (aRecSyntheseDoc.IndexRsltTotalTVA t2) or (aRecSyntheseDoc.IndexRsltTotalTVA -1) then
                    if ValeursEgales(_TotalHT + aRecSyntheseDoc.TotalTVA[t2].Valeur, aRecSyntheseDoc.TotalTTC[t3].Valeur) then
                    begin
                      UneCoherenceTrouvee := true;

                      aRecSyntheseDoc.IndexRsltTotalTTC := t3;
                      aRecSyntheseDoc.IndexRsltTauxTVA := t;
                      aRecSyntheseDoc.IndexRsltTotalTVA := t2;

                      // Ajouter le total HT :
                      Inc(aRecSyntheseDoc.LengthTotalHT);
                      SetLength(aRecSyntheseDoc.TotalHT, aRecSyntheseDoc.LengthTotalHT);
                      aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.LengthTotalHT-1].Valeur := _TotalHT;
                      aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.LengthTotalHT-1].AssociatedExpressionKeywordIndex := -1;
                      aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.LengthTotalHT-1].ExpressionIndex := UnDocument.FindExpression(_TotalHT, etFloat, 0, UnDocument.ExpressionCount-1);
                    end;
              end;
    except
    end;

  // 27/05/2012 - Ajouter total TVA grâce au taux (même si tableau non vide, car la valeur a pu être mal OCRisée) et valider avec Total TTC, taux TVA et total HT:
  if not UneCoherenceTrouvee then
    try
      if (aRecSyntheseDoc.IndexRsltTotalTTC -1) or (aRecSyntheseDoc.IndexRsltTauxTVA -1) or (aRecSyntheseDoc.IndexRsltTotalHT = -1) then
        for t3 := 0 to aRecSyntheseDoc.LengthTotalTTC-1 do
          if (aRecSyntheseDoc.IndexRsltTotalTTC t3) or (aRecSyntheseDoc.IndexRsltTotalTTC -1) then
            for t := 0 to aRecSyntheseDoc.LengthTauxTVA-1 do
              if ((t aRecSyntheseDoc.IndexRsltTauxTVA) or (aRecSyntheseDoc.IndexRsltTauxTVA -1))
                and (aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur > 0) and (aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur <> 100) then
              begin
                // Voir s' il y a une cohérence entre le TotalHT et le total TVA :
                for t2 := 0 to aRecSyntheseDoc.LengthTotalHT-1 do
                  if (aRecSyntheseDoc.IndexRsltTotalHT t2) or (aRecSyntheseDoc.IndexRsltTotalHT -1) then
                  begin
                    _TotalTVA := Arrondir( aRecSyntheseDoc.TotalHT[t2].Valeur * aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur / 100, 2 );

                    if ValeursEgales(_TotalTVA + aRecSyntheseDoc.TotalHT[t2].Valeur, aRecSyntheseDoc.TotalTTC[t3].Valeur) then
                    begin
                      UneCoherenceTrouvee := true;

                      aRecSyntheseDoc.IndexRsltTotalTTC := t3;
                      aRecSyntheseDoc.IndexRsltTauxTVA := t;
                      aRecSyntheseDoc.IndexRsltTotalHT := t2;

                      // Ajouter le total TVA :
                      Inc(aRecSyntheseDoc.LengthTotalTVA);
                      SetLength(aRecSyntheseDoc.TotalTVA, aRecSyntheseDoc.LengthTotalTVA);
                      aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.LengthTotalTVA-1].Valeur := _TotalTVA;
                      aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.LengthTotalTVA-1].AssociatedExpressionKeywordIndex := -1;
                      aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.LengthTotalTVA-1].ExpressionIndex := UnDocument.FindExpression(_TotalTVA, etFloat, 0, UnDocument.ExpressionCount-1);
                    end;
                  end;
              end;
    except
    end;

  // 27/05/2012 - Ajouter total TTC grâce au taux (même si tableau non vide, car la valeur a pu être mal OCRisée) et valider avec Total TVA, taux TVA et total HT:
  if not UneCoherenceTrouvee then
    try
      if (aRecSyntheseDoc.IndexRsltTotalTVA -1) or (aRecSyntheseDoc.IndexRsltTauxTVA -1) or (aRecSyntheseDoc.IndexRsltTotalHT = -1) then
        for t3 := 0 to aRecSyntheseDoc.LengthTotalTVA-1 do
          if (aRecSyntheseDoc.IndexRsltTotalTVA t3) or (aRecSyntheseDoc.IndexRsltTotalTVA -1) then
            for t := 0 to aRecSyntheseDoc.LengthTauxTVA-1 do
              if ((t aRecSyntheseDoc.IndexRsltTauxTVA) or (aRecSyntheseDoc.IndexRsltTauxTVA -1))
                and (aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur > 0) and (aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur <> 100) then
              begin
                // Voir s' il y a une cohérence :
                for t2 := 0 to aRecSyntheseDoc.LengthTotalHT-1 do
                  if (aRecSyntheseDoc.IndexRsltTotalHT t2) or (aRecSyntheseDoc.IndexRsltTotalHT -1) then
                  begin
                    _TotalTTC := Arrondir( aRecSyntheseDoc.TotalHT[t2].Valeur * (1 + aRecSyntheseDoc.TauxTVA[t].Valeurs[0].Valeur/100), 2 );

                    if ValeursEgales(aRecSyntheseDoc.TotalTVA[t3].Valeur + aRecSyntheseDoc.TotalHT[t2].Valeur, _TotalTTC) then
                    begin
                      UneCoherenceTrouvee := true;

                      aRecSyntheseDoc.IndexRsltTotalTVA := t3;
                      aRecSyntheseDoc.IndexRsltTauxTVA  := t;
                      aRecSyntheseDoc.IndexRsltTotalHT  := t2;

                      // Ajouter le total TTC :
                      Inc(aRecSyntheseDoc.LengthTotalTTC);
                      SetLength(aRecSyntheseDoc.TotalTTC, aRecSyntheseDoc.LengthTotalTTC);
                      aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.LengthTotalTTC-1].Valeur := _TotalTTC;
                      aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.LengthTotalTTC-1].AssociatedExpressionKeywordIndex := -1;
                      aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.LengthTotalTTC-1].ExpressionIndex := UnDocument.FindExpression(_TotalTTC, etFloat, 0, UnDocument.ExpressionCount-1);
                    end;
                  end;
              end;
    except
    end;

  // 23/04/2012 - Ajouter un Total TVA par rapport aux montants TVA :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.LengthTotalTVA 0) and (aRecSyntheseDoc.LengthSomme_MontantsTVA 1) then
      if UnDocument.FindExpression(aRecSyntheseDoc.Somme_MontantsTVA[0].Valeur, etFloat, 0, UnDocument.ExpressionCount-1) <> -1 then
      begin
        UneCoherenceTrouvee := true;
        aRecSyntheseDoc.LengthTotalTVA := 1;
        SetLength(aRecSyntheseDoc.TotalTVA, 1);
        aRecSyntheseDoc.TotalTVA[0].Valeur := aRecSyntheseDoc.Somme_MontantsTVA[0].Valeur;
        aRecSyntheseDoc.TotalTVA[0].AssociatedExpressionKeywordIndex := -1;
        aRecSyntheseDoc.TotalTVA[0].ExpressionIndex := UnDocument.FindExpression(aRecSyntheseDoc.Somme_MontantsTVA[0].Valeur, etFloat, 0, UnDocument.ExpressionCount-1);
      end;

  // 23/04/2012 - Ajouter un Total HT par rapport aux montants HT :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.LengthTotalHT 0) and (aRecSyntheseDoc.LengthSomme_MontantsHT 1) then
      if UnDocument.FindExpression(aRecSyntheseDoc.Somme_MontantsHT[0].Valeur, etFloat, 0, UnDocument.ExpressionCount-1) <> -1 then
      begin
        UneCoherenceTrouvee := true;
        aRecSyntheseDoc.LengthTotalHT := 1;
        SetLength(aRecSyntheseDoc.TotalHT, 1);
        aRecSyntheseDoc.TotalHT[0].Valeur := aRecSyntheseDoc.Somme_MontantsHT[0].Valeur;
        aRecSyntheseDoc.TotalHT[0].AssociatedExpressionKeywordIndex := -1;
        aRecSyntheseDoc.TotalHT[0].ExpressionIndex := UnDocument.FindExpression(aRecSyntheseDoc.Somme_MontantsHT[0].Valeur, etFloat, 0, UnDocument.ExpressionCount-1);
      end;

  // 23/04/2012 - Ajouter un Total TTC par rapport aux montants TTC :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.LengthTotalTTC 0) and (aRecSyntheseDoc.LengthSomme_MontantsTTC 1) then
      if UnDocument.FindExpression(aRecSyntheseDoc.Somme_MontantsTTC[0].Valeur, etFloat, 0, UnDocument.ExpressionCount-1) <> -1 then
      begin
        UneCoherenceTrouvee := true;
        aRecSyntheseDoc.LengthTotalTTC := 1;
        SetLength(aRecSyntheseDoc.TotalTTC, 1);
        aRecSyntheseDoc.TotalTTC[0].Valeur := aRecSyntheseDoc.Somme_MontantsTTC[0].Valeur;
        aRecSyntheseDoc.TotalTTC[0].AssociatedExpressionKeywordIndex := -1;
        aRecSyntheseDoc.TotalTTC[0].ExpressionIndex := UnDocument.FindExpression(aRecSyntheseDoc.Somme_MontantsTTC[0].Valeur, etFloat, 0, UnDocument.ExpressionCount-1);
      end;

  // Ajouter le Total TTC qui est un champ obligatoire si on ne l' a pas (quelques fois sur fond gris et donc, illisible) :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.IndexRsltTotalTTC -1) and (aRecSyntheseDoc.IndexRsltNetAPayer -1) then
      if aRecSyntheseDoc.LengthTotalTTC = 0 then
        if (aRecSyntheseDoc.IndexRsltTotalTVA <> -1) or (aRecSyntheseDoc.LengthTotalTVA = 1) then
          if (aRecSyntheseDoc.IndexRsltTotalHT <> -1) or (aRecSyntheseDoc.LengthTotalHT = 1) then
            begin
              UneCoherenceTrouvee := true;

              if aRecSyntheseDoc.IndexRsltTotalHT = -1 then
                aRecSyntheseDoc.IndexRsltTotalHT := 0;

              if aRecSyntheseDoc.IndexRsltTotalTVA = -1 then
                aRecSyntheseDoc.IndexRsltTotalTVA := 0;

              aRecSyntheseDoc.LengthTotalTTC := 1;
              SetLength(aRecSyntheseDoc.TotalTTC, 1);
              aRecSyntheseDoc.TotalTTC[0].Valeur := aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.IndexRsltTotalTVA].Valeur
                                                       + aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.IndexRsltTotalHT].Valeur;
              aRecSyntheseDoc.TotalTTC[0].AssociatedExpressionKeywordIndex := -1;
              aRecSyntheseDoc.TotalTTC[0].ExpressionIndex := UnDocument.FindExpression(aRecSyntheseDoc.TotalTTC[0].Valeur, etFloat, 0, UnDocument.ExpressionCount-1);
              aRecSyntheseDoc.IndexRsltTotalTTC := 0;
            end;

  // *** Cohérences par manipulation des éléments *** //

  // Quelques fois, il faut regrouper les éléments somme des montants HT en un seul élément :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.IndexRsltTotalHT -1) and (aRecSyntheseDoc.IndexRsltSomme_MontantsHT -1) then
      if aRecSyntheseDoc.LengthSomme_MontantsHT > 1 then
        while aRecSyntheseDoc.LengthSomme_MontantsHT > 1 do
        begin
          UneCoherenceTrouvee := true; // Va permettre de refaire une recherche

          while aRecSyntheseDoc.Somme_MontantsHT[1].LengthValeurs <> 0 do
          begin
            aRecSyntheseDoc.Somme_MontantsHT[0].LengthValeurs := aRecSyntheseDoc.Somme_MontantsHT[0].LengthValeurs + 1;
            SetLength(aRecSyntheseDoc.Somme_MontantsHT[0].Valeurs, aRecSyntheseDoc.Somme_MontantsHT[0].LengthValeurs);

            aRecSyntheseDoc.Somme_MontantsHT[0].Valeurs[aRecSyntheseDoc.Somme_MontantsHT[0].LengthValeurs-1].Valeur :=
                aRecSyntheseDoc.Somme_MontantsHT[1].Valeurs[0].Valeur;
            aRecSyntheseDoc.Somme_MontantsHT[0].Valeurs[aRecSyntheseDoc.Somme_MontantsHT[0].LengthValeurs-1].ExpressionIndex :=
                aRecSyntheseDoc.Somme_MontantsHT[1].Valeurs[0].ExpressionIndex;

            aRecSyntheseDoc.Somme_MontantsHT[0].Valeur := aRecSyntheseDoc.Somme_MontantsHT[0].Valeur + aRecSyntheseDoc.Somme_MontantsHT[1].Valeurs[0].Valeur;

            aRecSyntheseDoc.Somme_MontantsHT[1].LengthValeurs := aRecSyntheseDoc.Somme_MontantsHT[1].LengthValeurs - 1;
          end;

          aRecSyntheseDoc.LengthSomme_MontantsHT := aRecSyntheseDoc.LengthSomme_MontantsHT - 1;
          SetLength(aRecSyntheseDoc.Somme_MontantsHT, aRecSyntheseDoc.LengthSomme_MontantsHT);
        end;

  // Le total TVA peut se trouver à la fin des montants TVA (total de la colonne ou seule valeur de la colonne):
  if not UneCoherenceTrouvee then
    if aRecSyntheseDoc.LengthTotalTVA = 0 then
    begin
      // Copier le montant le plus grand dans Total TVA :
      aExpressionIndex := -1;
      TmpExtended := 0;
      ValeurMax := 1000000;
      for s := 0 to aRecSyntheseDoc.LengthSomme_MontantsTVA-1 do
        if aRecSyntheseDoc.Somme_MontantsTVA[s].Valeurs[aRecSyntheseDoc.Somme_MontantsTVA[s].LengthValeurs - 1].Valeur > TmpExtended then
          if aRecSyntheseDoc.Somme_MontantsTVA[s].Valeurs[aRecSyntheseDoc.Somme_MontantsTVA[s].LengthValeurs - 1].Valeur < ValeurMax then
          begin
            aExpressionIndex := aRecSyntheseDoc.Somme_MontantsTVA[s].Valeurs[aRecSyntheseDoc.Somme_MontantsTVA[s].LengthValeurs - 1].ExpressionIndex;
            aAssociatedExpressionKeywordIndex := aRecSyntheseDoc.Somme_MontantsTVA[s].AssociatedExpressionKeywordIndex;
            TmpExtended := aRecSyntheseDoc.Somme_MontantsTVA[s].Valeurs[aRecSyntheseDoc.Somme_MontantsTVA[s].LengthValeurs - 1].Valeur;
          end;

      if aExpressionIndex <> -1 then
      begin
        UneCoherenceTrouvee := true;
        Inc(aRecSyntheseDoc.LengthTotalTVA);
        SetLength(aRecSyntheseDoc.TotalTVA, aRecSyntheseDoc.LengthTotalTVA);
        aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.LengthTotalTVA-1].ExpressionIndex := aExpressionIndex;
        aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.LengthTotalTVA-1].AssociatedExpressionKeywordIndex := aAssociatedExpressionKeywordIndex;
        aRecSyntheseDoc.TotalTVA[aRecSyntheseDoc.LengthTotalTVA-1].Valeur := TmpExtended;
      end;
    end;

  // 05/05/2012
  // Le total HT peut se trouver à la fin des montants HT (total de la colonne ou seule valeur de la colonne):
  if not UneCoherenceTrouvee then
    if aRecSyntheseDoc.LengthTotalHT = 0 then
    begin
      // Copier le montant le plus grand dans Total HT :
      aExpressionIndex := -1;
      TmpExtended := 0;
      ValeurMax := 1000000;
      for s := 0 to aRecSyntheseDoc.LengthSomme_MontantsHT-1 do
        if aRecSyntheseDoc.Somme_MontantsHT[s].Valeurs[aRecSyntheseDoc.Somme_MontantsHT[s].LengthValeurs - 1].Valeur > TmpExtended then
          if aRecSyntheseDoc.Somme_MontantsHT[s].Valeurs[aRecSyntheseDoc.Somme_MontantsHT[s].LengthValeurs - 1].Valeur < ValeurMax then
          begin
            aExpressionIndex := aRecSyntheseDoc.Somme_MontantsHT[s].Valeurs[aRecSyntheseDoc.Somme_MontantsHT[s].LengthValeurs - 1].ExpressionIndex;
            aAssociatedExpressionKeywordIndex := aRecSyntheseDoc.Somme_MontantsHT[s].AssociatedExpressionKeywordIndex;
            TmpExtended := aRecSyntheseDoc.Somme_MontantsHT[s].Valeurs[aRecSyntheseDoc.Somme_MontantsHT[s].LengthValeurs - 1].Valeur;
          end;

      if aExpressionIndex <> -1 then
      begin
        UneCoherenceTrouvee := true;
        Inc(aRecSyntheseDoc.LengthTotalHT);
        SetLength(aRecSyntheseDoc.TotalHT, aRecSyntheseDoc.LengthTotalHT);
        aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.LengthTotalHT-1].ExpressionIndex := aExpressionIndex;
        aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.LengthTotalHT-1].AssociatedExpressionKeywordIndex := aAssociatedExpressionKeywordIndex;
        aRecSyntheseDoc.TotalHT[aRecSyntheseDoc.LengthTotalHT-1].Valeur := TmpExtended;
      end;
    end;

  // 05/05/2012
  // Le total TTC peut se trouver à la fin des montants TTC (total de la colonne ou seule valeur de la colonne):
  if not UneCoherenceTrouvee then
    if aRecSyntheseDoc.LengthTotalTTC = 0 then
    begin
      // Copier le montant le plus grand dans Total TTC :
      aExpressionIndex := -1;
      TmpExtended := 0;
      ValeurMax := 1000000;
      for s := 0 to aRecSyntheseDoc.LengthSomme_MontantsTTC-1 do
        if aRecSyntheseDoc.Somme_MontantsTTC[s].Valeurs[aRecSyntheseDoc.Somme_MontantsTTC[s].LengthValeurs - 1].Valeur > TmpExtended then
          if aRecSyntheseDoc.Somme_MontantsTTC[s].Valeurs[aRecSyntheseDoc.Somme_MontantsTTC[s].LengthValeurs - 1].Valeur < ValeurMax then
          begin
            aExpressionIndex := aRecSyntheseDoc.Somme_MontantsTTC[s].Valeurs[aRecSyntheseDoc.Somme_MontantsTTC[s].LengthValeurs - 1].ExpressionIndex;
            aAssociatedExpressionKeywordIndex := aRecSyntheseDoc.Somme_MontantsTTC[s].AssociatedExpressionKeywordIndex;
            TmpExtended := aRecSyntheseDoc.Somme_MontantsTTC[s].Valeurs[aRecSyntheseDoc.Somme_MontantsTTC[s].LengthValeurs - 1].Valeur;
          end;

      if aExpressionIndex <> -1 then
      begin
        UneCoherenceTrouvee := true;
        Inc(aRecSyntheseDoc.LengthTotalTTC);
        SetLength(aRecSyntheseDoc.TotalTTC, aRecSyntheseDoc.LengthTotalTTC);
        aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.LengthTotalTTC-1].ExpressionIndex := aExpressionIndex;
        aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.LengthTotalTTC-1].AssociatedExpressionKeywordIndex := aAssociatedExpressionKeywordIndex;
        aRecSyntheseDoc.TotalTTC[aRecSyntheseDoc.LengthTotalTTC-1].Valeur := TmpExtended;
      end;
    end;

  // *** Si rien d' autre a fonctionné *** //

  // Renvoyer au moins le champ obligatoire Total TTC si aucune valeur de la cohérence trouvée :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.IndexRsltTotalTTC -1) and (aRecSyntheseDoc.IndexRsltNetAPayer -1)
      and (aRecSyntheseDoc.IndexRsltTotalHT -1) and (aRecSyntheseDoc.IndexRsltTotalTVA -1) then
        if aRecSyntheseDoc.LengthTotalTTC > 0 then
        begin
          UneCoherenceTrouvee := True;
          aRecSyntheseDoc.IndexRsltTotalTTC := 0;
        end
        else
          if aRecSyntheseDoc.LengthNetAPayer > 0 then
          begin
            UneCoherenceTrouvee := True;
            aRecSyntheseDoc.IndexRsltNetAPayer := 0;
          end;

  // Récupérer la somme des montants TTC si on a rien trouvé :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.IndexRsltTotalTTC -1) and (aRecSyntheseDoc.IndexRsltNetAPayer -1)
      and (aRecSyntheseDoc.IndexRsltTotalHT -1) and (aRecSyntheseDoc.IndexRsltTotalTVA -1)
        and (aRecSyntheseDoc.IndexRsltSomme_MontantsTTC = -1) and (aRecSyntheseDoc.LengthSomme_MontantsTTC > 0) then
          if aRecSyntheseDoc.Somme_MontantsTTC[0].LengthValeurs = 1 then
            begin
              UneCoherenceTrouvee := True;
              aRecSyntheseDoc.IndexRsltSomme_MontantsTTC := 0;
            end;


  // *** Finalisation *** //

  // Renvoyer les frais de port si montants HT non trouvés :
  if not UneCoherenceTrouvee then
    if (aRecSyntheseDoc.IndexRsltSomme_MontantsHT -1) and (aRecSyntheseDoc.IndexRsltFraisDePort -1) and (aRecSyntheseDoc.LengthFraisDePort > 1) then
    begin
      UneCoherenceTrouvee := true;
      aRecSyntheseDoc.IndexRsltFraisDePort := 0;   // Celui trouvé par TcyDocER ...
    end;

  if (UneCoherenceTrouvee) and (Retours < 20) then
  begin
    Inc(Retours);

    Goto RelancerCoherence;
  end;
end;

end.



Composants Cindy pour Delphi
Faites une donation.
Commenter la réponse de cs_MAURICIO
Messages postés
991
Date d'inscription
samedi 25 octobre 2003
Statut
Membre
Dernière intervention
29 août 2013
5
0
Merci
je n'ai pas regardé en profondeur le code, mais pourquoi utilise tu un champ MonRec.LengthMachin plutôt que d'utiliser Length(MonRec.Machin) ?

Autre chose, a ta place, je remplacerai
initialise_SyntheseDoc(MonRecSyntheseDoc);
par
  DefaultRecSyntheseDoc: RecSyntheseDoc = (NumFacture_ExpressionIndex : -1;
                                           DateFacture_ExpressionIndex: -1;
                                           TVAIntracom_ExpressionIndex: -1;
                                           NumSiret_ExpressionIndex   : -1;
                                           Telephone_ExpressionIndex  : -1;
                                           Fax_ExpressionIndex        : -1;
                                           EMail_ExpressionIndex      : -1;
                                           Website_ExpressionIndex    : -1;
                                           NumClient_ExpressionIndex  : -1;

                                           IndexRsltSomme_MontantsTVA : -1;
                                           IndexRsltTauxTVA           : -1;
                                           IndexRsltTotalTVA          : -1;

                                           IndexRsltSomme_MontantsHT  : -1;
                                           IndexRsltTotalHT           : -1;
                                           IndexRsltRemiseHT          : -1;
                                           IndexRsltFraisDePort       : -1;

                                           IndexRsltSomme_MontantsTTC : -1;
                                           IndexRsltTotalTTC          : -1;
                                           IndexRsltDebitAnterieur    : -1;
                                           IndexRsltNetAPayer         : -1
  );


et j'ajouterai aussi un appel à CheckRecSyntheseDoc au debut et a la fin de Executer_CoherenceDoc, avec :
procedure CheckRecSyntheseDoc(const aRecSyntheseDoc: RecSyntheseDoc);
begin
  Assert(aRecSyntheseDoc.LengthSomme_MontantsTVA = Length(aRecSyntheseDoc.Somme_MontantsTVA));
  Assert(aRecSyntheseDoc.LengthTauxTVA           = Length(aRecSyntheseDoc.TauxTVA          ));
  Assert(aRecSyntheseDoc.LengthTotalTVA          = Length(aRecSyntheseDoc.TotalTVA         ));

  Assert(aRecSyntheseDoc.LengthSomme_MontantsHT  = Length(aRecSyntheseDoc.Somme_MontantsHT ));
  Assert(aRecSyntheseDoc.LengthTotalHT           = Length(aRecSyntheseDoc.TotalHT          ));
  Assert(aRecSyntheseDoc.LengthRemiseHT          = Length(aRecSyntheseDoc.RemiseHT         ));
  Assert(aRecSyntheseDoc.LengthFraisDePort       = Length(aRecSyntheseDoc.FraisDePort      ));

  Assert(aRecSyntheseDoc.LengthSomme_MontantsTTC = Length(aRecSyntheseDoc.Somme_MontantsTTC));
  Assert(aRecSyntheseDoc.LengthTotalTTC          = Length(aRecSyntheseDoc.TotalTTC         ));
  Assert(aRecSyntheseDoc.LengthDebitAnterieur    = Length(aRecSyntheseDoc.DebitAnterieur   ));
  Assert(aRecSyntheseDoc.LengthNetAPayer         = Length(aRecSyntheseDoc.NetAPayer        ));
end;
Commenter la réponse de Guillemouze
Messages postés
4200
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
2 janvier 2019
26
0
Merci
tu ne tire pas partis des nouveautés de D2009 !

Regarde cet exemple, il te fera gagner un grand nombre de variable à supprimer de ton record
Tu gagnera du temps en implementation et en interfacage.

Attention, c'est du lourd !

unit Unit1;

interface


uses
  Windows, SysUtils, Generics.Collections;

  {/* En mode "Yes we can !" */}

type
  TPointXY = packed record { Toujours en packed }
  public
    X, Y : integer; { Une structure simple pour l'exemple ... TPoint }

  public
    class function create(aX, aY: integer): TPointXY; static;    // p0 := TPointXY.Create(12, 24);
      { fonction statique qui permet de créer un TPointXY
        rapidement. Peut être appelée du type ou d'une variable :
          P0 := TPointXY.Create( Rect.Left, Rect.Top );
          ou
          P1 := P0.Create( Rect.Left-2, Rect.Top-2 );
      }

    procedure assign(aX, aY: integer);                           // p0.assign(24, 32);
      { fonction qui permet d'assigner X et Y en une seule ligne
          P1.Assign( Rect.Right, Rect.Bottom );
      }
    procedure reset;                                             // X=0 Y=0
      { fonction qui remet à zéro X et Y
          P1.Reset;
      }

    { Surcharge des opérateurs pour TPointXY }
    class operator explicit(A: Windows.TPoint): TPointXY;        // interroperability with Windows.TPoint
    { Assignation à un TPointXY à partir d'un TPoint
        P1 := Form1.ClientRect.TopLeft;
    }
    class operator explicit(A: TPointXY): Windows.TPoint;        // ''
    { Assignation à un TPoint à partir d'un TPointXY
        Form1.ClientRect.RightBottom := P1;
    }

    class operator explicit(A: TPointXY): string;                // str :p0;     -> str "X, Y"
    class operator implicit(A: TPointXY): string;                // string(p0);    -> ("X, Y")
    { Assignation explicite et implicite d'un TPointXY
      sur une chaine.
        LabelPoint.Caption := P0; // Explicit call
        Str := string(P0); // Implicit call
    }

    class operator equal(A,B: TPointXY): boolean;                // p0 p1         -> bool exp (A.X B.X) AND (A.Y = B.Y)
    class operator notEqual(A,B: TPointXY): boolean;             // p0 <> p1        -> bool exp (A.X <> B.X) OR (A.Y <> B.Y)

    class operator logicalOr(A: TPointXY; B: integer): boolean;  // p0 OR 12        -> bool exp (X 12) OR (Y 12)
    class operator logicalAnd(A: TPointXY; B: integer): boolean; // p0 AND 12       -> bool exp (X 12) AND (Y 12)
    class operator logicalXor(A: TPointXY; B: integer): boolean; // p0 XOR 12       -> bool exp (X 12) XOR (Y 12)

    class operator add(A, B: TPointXY): TPointXY;                // p2 :p0 + p1   -> p2.[X|Y] p0.[X|Y] + p1.[X|Y]
    class operator subtract(A, B: TPointXY): TPointXY;           // p2 :p0 - p1   -> p2.[X|Y] p0.[X|Y] - p1.[X|Y]

    //class operator greaterThan(A,B: TPointXY): boolean;          // p0 > p1       -> bool exp (A.X > B.X) OR (A.Y > B.Y)
    //class operator greaterThanOrEqual(A,B: TPointXY): boolean;   // p0 >= p1      -> bool exp (A.X >= B.X) OR (A.Y >= B.Y)
    //class operator lessThan(A,B: TPointXY): boolean;             // p0 < p1       -> bool exp (A.X < B.X) OR (A.Y < B.Y)
    //class operator lessThanOrEqual(A,B: TPointXY): boolean;      // p0 <= p1      -> bool exp (A.X <= B.X) OR (A.Y <= B.Y)
    //class operator multiply(A, B: TPointXY): TPointXY;           // p2 :p0 * p1   -> p2.[X|Y] p0.[X|Y] * p1.[X|Y]
    //class operator divide(A, B: TPointXY): TPointXY;             // p2 :p0 / p1   -> p2.[X|Y] round(p0.[X|Y] / p1.[X|Y])
    //class operator intDivide(A, B: TPointXY): TPointXY;          // p2 :p0 div p1 -> p2.[X|Y] p0.[X|Y] DIV p1.[X|Y]
    //class operator add(A: TPointXY; B: integer): TPointXY;       // p1 := p0 + 8
    //class operator substract(A: TPointXY; B: integer): TPointXY; // p1 := p0 - 8
    //class operator multiply(A: TPointXY; B: integer): TPointXY;  // p1 := p0 * 2
    //class operator multiply(A: TPointXY; B: extended): TPointXY; // p1 := p0 * sin(Pi*2)
    //class operator divide(A: TPointXY; B: integer): TPointXY;    // p1 := p0 / 2
    //class operator divide(A: TPointXY; B: extended): TPointXY;   // p1 := p0 / cos(Pi*2)
  end;

  { TPoints
    on utilise le type TList générique (pas le classes.TList ! nuance)
  }
  TPoints = TList<TPointXY>; // <- to easy, hop on a un Liste de TPointXY pas besoin de surcharger un classes.TList ...

  { Type de liste de Points
  }
  TCalcPointIndexs = (
    rpiA,
    rpiB,
    rpiSum,
    rpiDiff
  );

  { TCalc
    Permet de stocker 4 liste distinctes de Points :
      A et B, provenant de calculs ou d'une image etc.
      Sum     somme de A et B
      Diff    différence entre A et B
    La tache est simplifiée par l'utilisation du TList<> et de la surcharge des opérateurs sur TPointXY
  }
  TCalc = packed record
  private
    fInitialized: boolean; // controle d'initialisation True si Initialize à été appelée, sinon false
    function getMaxCountAB: integer; // renvois le Count de la plus petite des listes entre A et B
  public
    Points : array[TCalcPointIndexs] of TPoints; // 4 listes A, B, Sum et Diff
  public
    procedure MakeSum; // Construit la liste de sommes A+B
    procedure MakeDiff;// Construit la liste de différence A-B

    procedure Initialize;// à appeler pour initialiser les listes TPoints, Bloc Try / Finally requit !
    procedure Finalize;  // à appeler pour finaliser le TCalc (detruit les listes TPoints)
  end;


implementation


{ Ici, une implémentation fortement réduite grace au type TList<> générique et
  les surcharge d'opérateurs.

}

{ TCalc }

procedure TCalc.Finalize;
var i : TCalcPointIndexs;
begin
  assert(fInitialized, 'Calc not initialized.');

  for i := low(TCalcPointIndexs) to high(TCalcPointIndexs) do
    Points[i].Free;
end;

function TCalc.getMaxCountAB: integer;
begin
  assert(fInitialized, 'Calc not initialized.');

  if Points[rpiA].Count > Points[rpiB].Count then
    result := Points[rpiB].Count
  else
    result := Points[rpiA].Count;
end;

procedure TCalc.Initialize;
var i : TCalcPointIndexs;
begin
  if not fInitialized then
  begin
    fInitialized := true;
    for i := low(TCalcPointIndexs) to high(TCalcPointIndexs) do
    begin
      Points[i] := TPoints.Create;
      fInitialized := fInitialized and assigned(Points[i]);
    end;
  end;
end;

procedure TCalc.MakeDiff;
var I,C: integer;
begin
  assert(fInitialized, 'Calc not initialized.');

  Points[rpiDiff].Clear;

  C := getMaxCountAB;

  for I := 0 to C - 1 do
    Points[rpiDiff].Add( Points[rpiA].Items[I] - Points[rpiB].Items[I] );
end;

procedure TCalc.MakeSum;
var I,C: integer;
begin
  assert(fInitialized, 'Calc not initialized.');

  Points[rpiSum].Clear;

  C := getMaxCountAB;

  for I := 0 to C - 1 do
    Points[rpiSum].Add( Points[rpiA].Items[I] + Points[rpiB].Items[I] );
end;

{ TPointXY }

class operator TPointXY.add(A, B: TPointXY): TPointXY;
begin
  result.X := A.X + B.X;
  result.Y := A.Y + B.Y;
end;

procedure TPointXY.assign(aX, aY: integer);
begin
  X := aX;
  Y := aY;
end;

class function TPointXY.create(aX, aY: integer): TPointXY;
begin
  result.X := aX;
  result.Y := aY;
end;

class operator TPointXY.equal(A, B: TPointXY): boolean;
begin
  result :(A.X B.X) and (A.Y = B.Y);
end;

class operator TPointXY.explicit(A: TPointXY): string;
begin
  result := format('%d x %d',[A.X, A.Y]);
end;

class operator TPointXY.explicit(A: Windows.TPoint): TPointXY;
begin
  result.X := A.X;
  result.Y := A.Y;
end;

class operator TPointXY.explicit(A: TPointXY): Windows.TPoint;
begin
  result.X := A.X;
  result.Y := A.Y;
end;

class operator TPointXY.implicit(A: TPointXY): string;
begin
  result := A; // call Explicit(TPointX): string
end;

class operator TPointXY.logicalAnd(A: TPointXY; B: integer): boolean;
begin
  result :(A.X B) and (A.Y = B);
end;

class operator TPointXY.logicalOr(A: TPointXY; B: integer): boolean;
begin
  result :(A.X B) or (A.Y = B);
end;

class operator TPointXY.logicalXor(A: TPointXY; B: integer): boolean;
begin
  result :(A.X B) xor (A.Y = B);
end;

class operator TPointXY.notEqual(A, B: TPointXY): boolean;
begin
  result := (A.X <> B.X) or (A.Y <> B.Y);
end;

procedure TPointXY.reset;
begin
  X := 0;
  Y := 0;
end;

class operator TPointXY.subtract(A, B: TPointXY): TPointXY;
begin
  result.X := A.X - B.X;
  result.Y := A.Y - B.Y;
end;

end.


________________________________________________________
besoin de câbles audio, vidèo, informatique pas cher ?
Commenter la réponse de f0xi
Messages postés
2233
Date d'inscription
mardi 10 décembre 2002
Statut
Modérateur
Dernière intervention
15 décembre 2014
5
0
Merci
Merci Foxi,

je dois malheureusement mettre en stand by pour l' instant les modifications sugérées.
Je reviendrai sur ta méthode le moment venu.

a+


Composants Cindy pour Delphi
Faites une donation.
Commenter la réponse de cs_MAURICIO