IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Trame chaîne de caractères


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2013
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2013
    Messages : 20
    Points : 15
    Points
    15
    Par défaut Trame chaîne de caractères
    Bonjour,
    Je dois importer des données depuis un fichier excel ; nom, salaire, num de compte pour un éventuel virement de masse à la banque, jusque la tout marche bien, sauf que je suis obliger de suivre une logique de trame pour que ma banque valide mon fichier.
    J'avoue que mon code delphi est abominable

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    begin
    memo1.Lines.Add('10000000000000000000'+FormatDateTime('yyyymmddhhmmss', Date )+'EUR232');
    try
    FDTable1.First;
    while not FDTable1.EOF do
    begin
     
    Memo1.Lines.Add('04020022022780780'+'                          '+'MAD2'+StringReplace(Format('%*.*f', [16, 2, StrToFloat(FDTable1.Fieldbyname('salaire').asString)]), ' ', '0',[rfReplaceAll])+'                                     '+'00'+'                        '+'1STE'+'                   '+FDTable1.Fieldbyname('nom_prenom').asString+'022780' );
    FDTable1.Next;
    Je cherche a améliorer mon code et surtout de respecter la limite de zone comme expliquer en fichier attacher; ( nom avec une longueur de 20 caractères sinon espace) par contre les chiffres a compléter par des zéros,voir fichier en attachement.
    Bref je suis perdu la

    Merci
    Images attachées Images attachées  
    Fichiers attachés Fichiers attachés

  2. #2
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 070
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 070
    Points : 15 454
    Points
    15 454
    Billets dans le blog
    9
    Par défaut
    Bonjour ! Voici les deux ou trois suggestions que je ferais.

    1° Utiliser une variable temporaire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    var
      chaine: string;
    begin
      chaine := ...
     
      Memo1.Lines.Add(chaine);
    2° Aller la ligne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    s := '04020022022780780'
       + ' '
       + 'MAD2'
       + ...
    Ou comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    s :=
      '04020022022780780' +
      ' ' +
      'MAD2' +
      ...
    On peut même utiliser la fonction Concat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    s := Concat(
        '04020022022780780',
        ' ',
        'MAD2',
        ...
    3° Pour compléter une chaîne avec des espaces, la fonction Format fait encore l'affaire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      ShowMessage('"' + Format('%10s', ['toto']) + '"');
      ShowMessage('"' + Format('%*s', [10, 'toto']) + '"');
    Voilà ma contribution.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    tu peux aussi utiliser un struct

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
      TSIMTHeader = packed record
        A1: array[0..1] of AnsiChar;
        A2: array[0..2] of AnsiChar;
        B1: array[0..2] of AnsiChar;
        B2: array[0..2] of AnsiChar;
        // B3
        B3_1: array[0..2] of AnsiChar;
        B3_2: array[0..2] of AnsiChar;
      end;
      TSIMT = packed record
        Header: TSIMTHeader;
        // B4
        B4_1: array[0..7] of AnsiChar;
        B4_2: array[0..2] of AnsiChar;
        B4_3: array[0..2] of AnsiChar;
        B4_4: array[0..11] of AnsiChar;
        B5: array[0..3] of AnsiChar;
        B6: array[0..15] of AnsiChar;
     end;
    il faut TOUT déclarer
    Ensuite juste via du transpypage, tu peux transformer un AnsiString en TSIMT04, et via un Move facilement recopier un TSIMT04 dans un AnsiString

    Tu gère ainsi réellement le format de fichier,
    En encapsulant le tout dans un objet , tu auras un code plus compréhensible,
    pense si un jour un autre reprend ton code et doit changer un truc dans "'04020022022780780'" ...
    Niveau évolution c'est peu pertinent !

    Sans parler de la gestion des positions, il faut compter caractère par caractère pour savoir quoi est quoi !
    Si tu veux mettre une valeur dans C10 il te faut contaténer tout avant, avec le struct, tu peux directement taper dans C10 !

    Et ensuite rien n'empeche d'écrire une constante


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    const
      SIMT04Header: TSIMTHeader =
      (
        A1: '04';
        A2: '020';
        B1: '022';
        B2: '022';
        B3_1: '780';
        B3_2: '780';
      );
    Tu notes que l'on comprend quelles valeurs va dans quelle colonne ... plus lisible que 04020022022780780

    le remplissage demande une maitrise du type PChar
    C'est le point noir de cette approche

    le mieux est d'encapsuler cela dans un objet car StrPCopy ce n'est pas très lisible
    l'encapsulation offrira les Getter et Setter nécessaires !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    var
      S: AnsiString;
      Smith: TSIMT;
    begin
      // que des Espaces !
      FillChar(Smith, SizeOf(Smith), Ord(' '));
      // copie de la base 04020022022780780 !
      Move(SIMT04Header, Smith, SizeOf(SIMT04Header));
      // valeurs calculées
      Smith.B5 := 'MAD2';
      StrPCopy(@Smith.B6, AnsiStrings.StringReplace(AnsiStrings.Format('%16.2f', [1.1]), ' ', '0', [rfReplaceAll])); 
      // Copie de la structure dans un buffer
      SetLength(S, SizeOf(Smith));
      Move(Smith, PAnsiChar(S)^, SizeOf(Smith));
      // Ecriture du buffer dans un fichier
      with TStringList.Create do
      try
        Add(S);
        SaveToFile('SIMT04.txt');
      finally
        Free();
      end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2013
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2013
    Messages : 20
    Points : 15
    Points
    15
    Par défaut
    Merci beaucoup pour vos contributions
    J'ai essayé bêtement de reproduire votre exemple mais malheureusement j'ai un access violation apres exécution; apparemment le problème provient de cette ligne : Move(Smith, PAnsiChar(S)^, SizeOf(Smith));
    Est-ce que c'est possible de m'aider dans ce sens
    Pour la première contribution tout marche bien sauf que j'ai des lignes décaler par rapport aux nombres de caractères sur la prétendante variable ex:

    NOM_PRENOM_N1 022780230780
    NOM_PRENOM_NN1 022780230780
    NOM_PRENOM_NNN1 022780230780
    Normalement ils doivent être aligner sans prendre en considération la langueur de la première colonne, chaque variable à une longueur fixe


    Merci

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Pour la proposition de Roland Chastain, pense à Paddé les champs avec des StringOfChar
    Son code est juste une idée de présentation

    pour appliquer la syntaxe proposée par Roland Chastain, il te faut conserver tes espaces !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    s := '04020022022780780'
      + '                          '
      + 'MAD2'
      + StringReplace(Format('%*.*f', [16, 2, StrToFloat(FDTable1.Fieldbyname('salaire').asString)]), ' ', '0',[rfReplaceAll])
      + '                                     '
      + '00'
      + '                        '
      + '1STE' 
      +'                   '
      + FDTable1.Fieldbyname('nom_prenom').asString // ICI il faut paddé !!!!
      + '022780';
    Memo1.Lines.Add(s);
    ICI il faut paddé à 35

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      + FDTable1.Fieldbyname('nom_prenom').asString + StringOfChar(' ', 35 - Length(FDTable1.Fieldbyname('nom_prenom').asString))
    Voir si le Format gère un pad avec espace sur une chaine, moi j'avais fait mes fonctions pour cela !



    Pour la variante Array Of Char

    Je suis sur XE2 donc j'ai tenté de gérer correctement en Ansi
    Sur mon XE2, le code fourni fonctionne (je l'ai testé)

    Les SetLength sont très importants, as-tu recopié directement ou fait quelques modifs par ci par là !

    Pense à mettre AnsiStrings dans les uses !
    AnsiStrings est nécessaire pour que le StrPCopy fonctionne correctement sur une source Ansi !

    Je n'avais pas gardé le code, j'ai copié depuis le forum et mis dans un bouton, le fichier est généré sans erreur
    Comme je le disais cette approche par Move et transtypage est réservé à des développeurs habitués au Pointer
    Et SURTOUT à ne pas utiliser sans une encapsulation objet qui gère la mémoire et facile l'utilisation de ton générateur de fichier !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    procedure TForm1.Button1Click(Sender: TObject);
    type
      TSIMTHeader = packed record
        A1: array[0..1] of AnsiChar;
        A2: array[0..2] of AnsiChar;
        B1: array[0..2] of AnsiChar;
        B2: array[0..2] of AnsiChar;
        // B3
        B3_1: array[0..2] of AnsiChar;
        B3_2: array[0..2] of AnsiChar;
      end;
      TSIMT = packed record
        Header: TSIMTHeader;
        // B4
        B4_1: array[0..7] of AnsiChar;
        B4_2: array[0..2] of AnsiChar;
        B4_3: array[0..2] of AnsiChar;
        B4_4: array[0..11] of AnsiChar;
        B5: array[0..3] of AnsiChar;
        B6: array[0..15] of AnsiChar;
     end;
    const
      SIMT04Header: TSIMTHeader =
      (
        A1: '04';
        A2: '020';
        B1: '022';
        B2: '022';
        B3_1: '780';
        B3_2: '780';
      );
     
     
    var
      S: AnsiString;
      Smith: TSIMT;
    begin
      // que des Espaces !
      FillChar(Smith, SizeOf(Smith), Ord(' '));
      // copie de la base 04020022022780780 !
      Move(SIMT04Header, Smith, SizeOf(SIMT04Header));
      // valeurs calculées
      Smith.B5 := 'MAD2';
      StrPCopy(@Smith.B6, AnsiStrings.StringReplace(AnsiStrings.Format('%16.2f', [1.1]), ' ', '0', [rfReplaceAll]));
      // Copie de la structure dans un buffer
      SetLength(S, SizeOf(Smith));
      Move(Smith, PAnsiChar(S)^, SizeOf(Smith));
      // Ecriture du buffer dans un fichier
      with TStringList.Create do
      try
        Add(S);
        SaveToFile('SIMT04.txt');
      finally
        Free();
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  6. #6
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Décembre 2013
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2013
    Messages : 20
    Points : 15
    Points
    15
    Par défaut
    Merci beaucoup pour votre aide si précieuse

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 12/02/2013, 01h08
  2. Réponses: 2
    Dernier message: 18/10/2003, 14h42
  3. Chaînes de caractères
    Par Zazeglu dans le forum C
    Réponses: 3
    Dernier message: 28/08/2003, 16h20
  4. Inverser une chaîne de caractères
    Par DBBB dans le forum Assembleur
    Réponses: 2
    Dernier message: 30/03/2003, 11h09
  5. Réponses: 3
    Dernier message: 09/05/2002, 01h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo