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

API, COM et SDKs Delphi Discussion :

Définir le séparateur d'un fichier csv depuis delphi


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2011
    Messages : 63
    Points : 44
    Points
    44
    Par défaut Définir le séparateur d'un fichier csv depuis delphi
    Bonjour à toutes
    Y a-t-il un moyen sous delphi de mettre le séparateur d'un fichier .csv à point-virgule ? Sinon quel est le séparateur par défaut d'un fichier lorsqu'on change son extension manuellement, exemple : de .xls à .csv ?
    J'essaie d'importer un fichier csv en utilisant cette requete mais à chaque fois, il faut que je rentre manuellement dans le fichier excel en question pour faire enregistrer sous et choisir la bonne l'extension .csv avec le bon séparateur.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    BULK
    INSERT Test_2
    FROM 'C:\Users\akournane\Desktop\Test.csv'
    WITH
    (
    FIELDTERMINATOR = ';',
    ROWTERMINATOR = '\n',
    FIRSTROW = 2
    )
    GO
    Je vous remercie d'avance pour toute réponse ou aide.

  2. #2
    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 844
    Points
    24 844
    Par défaut
    Tu confonds le format de donnée Excel et CSV
    L'extension est à titre indicatif mais ne garanti pas que le format de donnée du fichier

    Certe, Excel comprend que si on lui fourni un fichier texte en CSV avec l'extension ".xls", il arrive à l'ouvrir
    Il supporte, la virgule classique, le point-virgule français et même un fichier tabulé (TSV)

    Mais un vrai fichier Excel c'est un binaire, soit un binaire brut soit un XML compressé
    Changer l'extension n'a aucun effet sur le contenu
    Excel te l'affiche en tableau mais la donnée est bien plus complexe qu'un fichier texte avec séparateur

    En Delphi, tu peux invoquer EXCEL en OLE pour faire un WorkBook.SaveAs(xlCSV) en forçant le type de données attendu
    xlCSV c'est Comma (virgule)
    Pour la version Semi-Colon (Point-virgule), c'est une valeur négative en -5000 ou si tu as de la chance, en Local à True.

    Ensuite, tu ne précise pas le SGBD, donc comment veux-tu que l'on puisse répondre à un SQL hors contexte même si l'on suppose que le BULK INSERT c'est surement du SQL Server
    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

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2011
    Messages : 63
    Points : 44
    Points
    44
    Par défaut
    Oui, il s'agit de sql server. Voici ce que je cherche à faire exactement depuis delphi, convertir un fichier .dbf en .csv (avec séparateur point virgule) ou alors en un autre format dont je connaîtrais le séparateur pour ensuite insérer ce fichier dans sql server avec "BULK INSERT". J'ai pu convertir un fichier .dbf en .csv (avec séparateur point virgule) mais manuellement sous excel, je cherche à le faire en passant par delphi.

  4. #4
    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 844
    Points
    24 844
    Par défaut
    Par ADO
    Ouvre DBF via un TADOTable, et fait toi même une fonction de conversion, c'est une boucle sur les enregistrements et une bouche sur les colonnes
    C'est très simple

    Le driver c'est "Microsoft Access dBASE Driver"
    Si tu n'as pas eu de soucis avec Excel, cela passera aussi en Delphi, c'est que tu as une structure dBASE classique.
    J'utilisais Apollo Engine avec lequel on pouvait avoir des fichiers dBASE avec une version trop récente et mal supportée par EXCEL

    BDE (obsolète mais toujours utile)
    En tout cas, le TTable du BDE peut le faire en type ttASCII
    Deux TTable l'un en DBF et l'autre en ASCII, un TBatchMove et il n'y a quasiment aucun code à écrire
    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

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2011
    Messages : 63
    Points : 44
    Points
    44
    Par défaut
    Merci mais je ne peux pas faire de boucle sur les enregistrements, pour plusieurs raisons et notamment parce qu'il y en a près de 3 millions pour certaines tables. Je dois éviter d'interroger les tables dbase. Ce que je dois faire est de les convertir vers un fichier csv ou un autre format (xls ou autre) qui préserverait l'intégrité des données. J'ai essayé avec ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Var Fichier: AnsiString; X: Variant;
     
    Fichier:='C:\Users\akournane\Desktop\bl3.csv';
    createfile('C:\Users\akournane\Desktop\bl3.csv',0,0,0,CREATE_NEW,FILE_ATTRIBUTE_Normal,0);
    CopyFile(PChar('C:\Users\akournane\Desktop\Mirroir\bl3.dbf'),PChar(Fichier), False);
    X:=CreateOleObject('Excel.Application');
    X.WorkBooks.Open(Fichier);
    X.ActiveWorkbook.SaveAs(Fichier, $00000006);
    X.Application.Quit;
    X:=unassigned;
    ça marche mais le fichier csv résultant contient les meme colonnes que la table dbf ne comporte pas le même nombre de ligne, et dans certains cas, il présente les données d'une manière incorrecte c'est à dire pas bien organisées en colonnes. J'aimerai aussi savoir s'il y a un moyen d'éviter les boites de dialogue générées par "SaveAs" et "Quit", c'est à dire écraser directement les fichiers présents au lieu de me le demander.

    Merci d'avance.

  6. #6
    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 844
    Points
    24 844
    Par défaut
    Comment veux-tu convertir un fichier en format dBASE vers CSV, EXCEL ou XML sans le lire ???

    Je ne vois pas le problème de faire une boucle pour la conversion sur le fichier copié

    1- Tu copies le fichier DBF via CopyFile vers un nouveau fichier DBF dans un autre répetoire, voire même une autre machine
    2- Tu ouvres la copie du fichier DBF, je précise bien la copie !
    3- Tu convertis la Copie en CSV via les boucles
    4- Tu supprimes la Copie DBF
    4- Tu lances SQL Server pour import le CSV

    Le Open et le SaveAs de Excel font ce travail de boucle,
    c'est juste que tu ne le vois pas !

    Au moins en le faisant via un composant DB que tu maitrises, tu devrais avoir un contenant correct
    Tes erreurs de lignes sont surement lignés au ligne supprimé qui en dBASE ne le sont pas vraiment, il faut faire un PACK de la table pour dégager toute trace d'éléments supprimés
    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

  7. #7
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Août 2008
    Messages
    666
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2008
    Messages : 666
    Points : 643
    Points
    643
    Par défaut
    Bonsoir,

    tu peux convertir ta table DBF en CVS utilisant la procédure suivante:

    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
    procedure WriteDataSetToCSV(DataSet: TDataSet, FileName: String);
    var
      List: TStringList;
      S: String;
      I: Integer;
    begin
      List := TStringList.Create;
      try
        DataSet.First;
        while not DataSet.Eof do
        begin
          S := '';
          for I := 0 to DataSet.FieldCount - 1 do
          begin
            if S > '' then
              S := S + ',';
            S := S + '"' + DataSet.Fields[I].AsString + '"';
          end;
          List.Add(S);
          DataSet.Next;
        end;
      finally
        List.SaveToFile(FileName);
        List.Free;
      end;
    end;

    utilisation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WriteDataSetToCSV(table1 , 'C:\TEST.csv');

  8. #8
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 029
    Points : 40 927
    Points
    40 927
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    sans boucle (enfin visible) et puisque BDE il y a et comme ShaileTroll l'a indiqué il y a le batchmove

    j'ai fait un essai (rapide)
    le code simple : Table2Destination.Batchmove(Table1Source,batcopy);cependant cela ne produit pas un fichier csv mais un fichier de longueur fixe et donc de champs fixe
    deux choses clochent cependant le 'point décimal' qui doit être un point et le format des dates (entre autre l'année sur 4 chiffre plutôt que 2)

    Maintenant si l'on regarde dans le répertoire où s'est passé l'opération on y découvre un fichier d'extension sch
    en l'ouvrant (ici le fichier à obtenir se nommait test.csv):
    [TEST]
    Filetype=Fixed
    CharSet=ascii
    Field1=CLE,Long Integer,11,00,00

    Field2=H1,Time,10,00,11

    Field3=H2,Time,10,00,21

    Field4=T1,Float,20,02,31
    avec un peu de recherche on trouve une explication sur ce fichier
    resterai donc à le transformer en
    [TEST]
    Filetype=Varying;
    Delimiter="
    Separator=,
    CharSet=ascii
    Field1=CLE,Long Integer,11,00,00

    Field2=H1,Time,10,00,11

    Field3=H2,Time,10,00,21

    Field4=T1,Float,20,02,31
    Oui, mais non ! Le fichier sch se remet comme au départ et une instruction de type DecimalSeparator:='.' n'est pas pris en compte
    la solution pour que le fichier SCH soit pris en compte est d'avoir un fichier de destination déjà créé mais vide et d'utiliser batAppend au lieu de batCopy (facile)
    et de modifier le comportement du BDE pour les dates et le point décimal (partie configuration du BDE, Configuration/Système/Formats)

    et c'est presque parfait , presque, car les valeurs numériques,dates (et temps) ne sont pas délimitées
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  9. #9
    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 844
    Points
    24 844
    Par défaut
    Citation Envoyé par NABIL74 Voir le message
    tu peux convertir ta table DBF en CVS utilisant la procédure suivante:
    Tu n'as pas noté que les fichiers faisait 3 millions de lignes, avec un TStringList c'est beaucoup de RAM consommé avec un risque de saturation
    Avec l'Unicode, suffit d'avoir un enregistrement de 350 caractères pour saturer la machine !

    C'est pour cela que j'avais proposé une fonction ExportToCSV qui utilise TextFile et ne consomme que peu de RAM

    D'ailleurs, voici une nouvelle version ExportToCSV qui gère le Quote si le séparateur est présent dans la donnée,
    c'est ton code,NABIL74 , qui m'y a fait penser

    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
    58
    59
    60
    61
    62
    63
    64
    65
     
      TDataSetSliteHelper = class helper for TDataSet
      public
        procedure ExportToCSV(const AFileName: TFileName; AWithHeader: Boolean; ASeparator: Char = ';');
      end;
     
    //------------------------------------------------------------------------------
    procedure TDataSetSliteHelper.ExportToCSV(const AFileName: TFileName; AWithHeader: Boolean; ASeparator: Char = ';'; AQuote: Char = '"');
    var
      fExport: TextFile;
      Data: TStringDynArray;
      sLigne, sCol: string;
      I: Integer;
      FBookmark: TBookmark;
    begin
      // RFC 4180 - Common Format and MIME Type for Comma-Separated Values (CSV) Files
      // The last field in the record must not be followed by a comma = La dernière colonne ne se termine pas par un séparateur !
     
      AssignFile(fExport, AFileName);
      Rewrite(fExport);
      try
        SetLength(Data, FieldCount);
     
        // Ligne d'en-tête
        if AWithHeader then
        begin
          for I := 0 to FieldCount - 1 do
            Data[I] := Fields[i].FieldName;
     
          sLigne := SLT.Common.StrUtilsEx.ImplodeLazy(Data, ASeparator);
          Writeln(fExport, sLigne);
        end;
     
        // Enregistrements
        DisableControls();
        try
          FBookmark := Bookmark;
          try
            First();
            while not Eof do
            begin
              for I := 0 to FieldCount - 1 do
              begin
                sCol := Fields[i].AsString;
                if ContainsStr(sCol, ASeparator) then
                  sCol := AQuote + sCol + AQuote;
     
                Data[I] := sCol;
              end;
     
              sLigne := SLT.Common.StrUtilsEx.ImplodeLazy(Data, ASeparator);
              Writeln(fExport, sLigne);
     
              Next();
            end;
          finally
            Bookmark := FBookmark;
          end;
        finally
          EnableControls();
        end;
      finally
        CloseFile(fExport);
      end;
    end;
    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
    {* -----------------------------------------------------------------------------
    la fonction ImplodeLazy retourne une chaine présentant toutes les chaînes du paramètre A comme une seule chaîne délimitée par le séparateur fourni par le Separator.
    @paramTableau de Chaine qui contient les chaines
    @param Separator Caractère qui délimitent une chaine pour la concaténation
    @param ADoubleParseMode Le double parsage réduit les réallocations et peut améliorer sensiblement les performances sous D4 à D7, le gain est proche de 95%, c'est moins notable (environ 60%) sous FastMM et les Delphi postérieurs à la version D2006
    @return Chaine concaténée
    ------------------------------------------------------------------------------ }
    function ImplodeLazy(const A: System.Types.TStringDynArray; Separator: Char; ADoubleParseMode: Boolean = {$IF CompilerVersion >= CompilerVersion2006}False{$ELSE}True{$IFEND}): string;
    var
      I: Integer;
      Len: Integer;
      pResult, pSource, pS: PChar;
      MoveCount: Integer;
    begin
      if Length(A) > 0 then
      begin
        if ADoubleParseMode then
        begin
          Len := Length(A[0]);
          for I := Succ(Low(A)) to High(A) do
            Inc(Len, 1 + Length(A[I]));
     
          SetLength(Result, Len);
          if Len > 0 then
          begin
            pResult := Pointer(Result);
            pSource := Pointer(A[0]);
            pS := @Separator;
     
            FillChar(pResult^, Len* SizeOf(Char), 0);
            MoveCount := Length(A[0]);
            Move(pSource^, pResult^, MoveCount * SizeOf(Char));
            Inc(pResult, MoveCount);
     
            for I := Succ(Low(A)) to High(A) do
            begin
              MoveCount := 1;
              Move(pS^, pResult^, MoveCount * SizeOf(Char));
              Inc(pResult, MoveCount);
     
              pSource := Pointer(A[I]);
              MoveCount := Length(A[I]);
              Move(pSource^, pResult^, MoveCount * SizeOf(Char));
              Inc(pResult, MoveCount);
            end;
          end;
        end
        else
        begin
          Result := A[0];
          for I := Succ(Low(A)) to High(A) do
            Result := Result + Separator + A[I];
        end;
      end
      else
        Result := '';
    end;
    Maintenant, la tache ardue reste de convaincre kournane que boucler sur la copie n'est pas un problème !



    Sergio, quel maitrise du BatchMove !
    Je ne le connais que de nom
    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

  10. #10
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 029
    Points : 40 927
    Points
    40 927
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Sergio, quel maitrise du BatchMove !
    maitrise c'est beaucoup dire, j'ai un peu galéré, un peu "googlé" et basta. De plus je me suis attaché aux composants de base de D7 car rien est indiqué, avec XE4 et plus (apparition de Firedac , Firedac à même remis le batchmove au goût du jour dans les versions récentes) il doit être possible de s'affranchir du BDE .

    Enfin ce truc est "vendu" pour faire à minima du 500 lignes secondes, je dirais que j'ai lu
    153000 records the execute of the batchmove takes about
    7 seconds.
    mais qu'au dessus de 150000 les perfs se dégradaient beaucoup
    je pense que pour des raisons évidente il serait mieux de se faire des requêtes pour faire le batappend en petit bloc
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

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

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 490
    Points : 2 752
    Points
    2 752
    Billets dans le blog
    10
    Par défaut Un exemple
    Voici un exemple que j'ai utilisé chez un client pour recharger complètement une base SQL à partir d'une base PARADOX. Cet application a fonctionné pendant une dizaine d'années.
    Tu peux t'en inspirer

    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
     
    unit ImportDonnees1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,  DB, DBTables, Data.DBXOdbc, Data.FMTBcd,
      Data.SqlExpr, Data.DBXMSSQL;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Edit1: TEdit;
        Memo1: TMemo;
        SQLQuery1: TSQLQuery;
        SQLQuery2: TSQLQuery;
        SQLConnection1: TSQLConnection;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        Procedure ExecuterSQL(st1 : string; b1 : boolean) ;
        function PreparationBase (sl_SQL : TStringList) : boolean;
        function ImportStructureParadoxVersSQLServer(sl_SQL : TStringList; st_chemin, st_table : string) : boolean;
        function ImportDonneesParadoxVersSQLServer1 (sl_SQL, sl_PbSQL : TStringList; st_chemin, st_table : string) : boolean;
      public
        { Public declarations }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    const
      K1 = 'HANDICR' ;
    var
      Sl1, Sl2 : TStringList ;
      s1 : smallint ;
    begin
      Top := 0 ;
      Left := 400 ;
      Memo1.Lines.Clear ;
      Sl1 := TStringList.Create;
      Sl2 := TStringList.Create;
      Session.GetAliasNames(Sl1);
      for s1 := 0 to (Sl1.Count-1) do
        if UpperCase(Sl1[s1]) = K1 then
        begin
          Session.GetAliasParams(Sl1[s1],Sl2);
           Edit1.Text := Copy(Sl2[0],6,255) ;
        end ;
      sl1.free ;
      sl2.free ;
    end;
     
    function TForm1.PreparationBase(sl_SQL: TStringList): boolean;
    begin
      result := true ;
      sl_SQL.Clear ;
      sl_SQL.Add('DBCC SHRINKDATABASE (''BaseAnaCol'', 10)') ;   
      sl_SQL.Add('SET DATEFORMAT mdy') ;
    end;
     
    function TForm1.ImportStructureParadoxVersSQLServer(sl_SQL : TStringList; st_chemin, st_table : string) : boolean;
    var
      st_TbSQL, st_tmp, st_key : string;
      Tb : TTable;
      i, j : integer;
      b_PrimaryKey : boolean;
    begin
      result := True;
      form1.caption := st_table ;
      try
        // DEBUT
        st_TbSQL := Copy(st_table, 1, Pos('.', st_table)-1);
        Tb := TTable.Create(nil);
        Tb.TableType := ttParadox;
        Tb.DatabaseName := st_chemin;
        Tb.TableName := st_table;
        Tb.Exclusive := True;
        Tb.Open;
        Tb.IndexDefs.Update ;
        Tb.FieldDefs.Update ;
        // suppression table si elle existe
        sl_SQL.Add('if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[' + st_TbSQL + ']'') and OBJECTPROPERTY(id, N''IsUserTable'') = 1)');
        sl_SQL.Add('drop table [dbo].[' + st_TbSQL + ']');
        // création table
        if Tb.Fields.Count > 0 then
        begin
          st_tmp := '';
          for i := 0 to (Tb.Fields.Count - 1) do
          begin
            case Tb.Fields[i].DataType of
              ftSmallint    : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [smallint],';
              ftInteger     : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [int],';
              ftFloat       : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [float],';
              ftCurrency    : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [money],';
              ftDate        : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [datetime],';
              ftTime        : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [datetime],';
              ftDateTime    : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [datetime],';
              ftString      : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [varchar] (' + IntToStr(Tb.Fields[i].DataSize) + '),';
              ftMemo        : st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [varchar] (5000),';
              else            st_tmp := st_tmp + ' [' + Tb.Fields[i].FieldName + '] [varchar] (5000),';
            end;
            for j := 0 to (Tb.IndexDefs.Count - 1) do
              if pos(Tb.Fields[i].FieldName, Tb.IndexDefs.Items[j].Fields) > 0 then
              begin
                delete(st_tmp, length(st_tmp), 1); // retraît dernière virgule
                st_tmp := st_tmp + ' not null,';
                break;
              end;
          end;
          delete(st_tmp, length(st_tmp), 1); // retraît dernière virgule
          sl_SQL.Add('CREATE TABLE [dbo].[' + st_TbSQL + '] (');
          sl_SQL.Add(st_tmp);
          sl_SQL.Add(') ON [PRIMARY]');
        end;
        // création index primaires
        if Tb.IndexDefs.Count > 0 then
        begin
          b_PrimaryKey := False;
          st_tmp := '';
          for i := 0 to (Tb.IndexDefs.Count - 1) do
            if ixPrimary in Tb.IndexDefs.Items[i].Options then
            begin
              b_PrimaryKey := True;
              st_key := Tb.IndexDefs.Items[i].Fields;
              if pos(';', st_key) = 0 then
                st_tmp := st_tmp + ' [' + st_key + '],'
              else
              begin
                while pos(';', st_key) > 0 do
                begin
                  st_tmp := st_tmp + ' [' + copy(st_key, 1, pos(';', st_key)-1) + '],';
                  delete(st_key, 1, pos(';', st_key));
                end;
                st_tmp := st_tmp + ' [' + st_key + '],';
              end;
            end;
          if b_PrimaryKey then
          begin
            delete(st_tmp, length(st_tmp), 1); // retraît dernière virgule
            sl_SQL.Add('ALTER TABLE [dbo].[' + st_TbSQL + '] WITH NOCHECK ADD');
            sl_SQL.Add('	CONSTRAINT [PK_' + st_TbSQL + '] PRIMARY KEY  CLUSTERED');
            sl_SQL.Add('	(');
            sl_SQL.Add('    ' + st_tmp);
            sl_SQL.Add('	)  ON [PRIMARY]');
          end;
        end;
        // FIN
        Tb.Close;
        Tb.Exclusive := False;
        Tb.Free;
      except
        on E : Exception do
        begin
          result := False;
        end;
      end;
    end;
     
     
    function TForm1.ImportDonneesParadoxVersSQLServer1(sl_SQL, sl_PbSQL: TStringList; st_chemin, st_table: string): boolean;
    var
      st_TbSQL, st1, st_tmp2, st2 : string;
      i : integer;
      Tb: TTable;
     
      procedure ConvertirChaine (var st1 : string) ;
      const
        //st2 :=        ' !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ*¡¢£¤¥¦§¨©ª«¬*®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ' ;
          K2 : string = ' _"_______*_ _ _0123456789_______ABCDEFGHIJKLMNOPQRSTUVWXYZ______ABCDEFGHIJKLMNOPQRSTUVWXYZ___            S   Z           S   ZY                                AAAAAA?CEEEEIIIIDNOOOOO OUUUUY??AAAAAAACEEEEIIIIONOOOOO_OUUUUYBY' ;
     
      var
        i1, i2, i3 : integer;
      begin
        i2 := length(st1);
        for i1:=1 to i2 do
        begin
          i3 := ord(st1[i1]) ;
          if i3 < 32 then
            st1[i1] := ' '
          else
            st1[i1] := K2[i3-31] ;
        end ;
        st1 := trim(st1) ;
        st1 := stringReplace (st1,'  ',' ', [rfReplaceAll,rfIgnoreCase]) ;
        st1 := stringReplace (st1,'_','', [rfReplaceAll,rfIgnoreCase]) ;
      end;
     
      procedure ConvertirChaineEmail (var st1 : string) ;
      const
        //st2 :=        ' !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ*¡¢£¤¥¦§¨©ª«¬*®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ' ;
          K2 : string = ' _____________._0123456789______@abcdefghijklmnopqrstuvwxyz______abcdefghijklmnopqrstuvwxyz_______________S___Z___________S___ZY________________________________aaaaaa?ceeeeiiiidnooooo ouuuuy??aaaaaaaceeeeiiiionooooo_ouuuuyby' ;
     
      var
        i1, i2, i3 : integer;
      begin
        i2 := length(st1);
        for i1:=1 to i2 do
        begin
          i3 := ord(st1[i1]) ;
          if i3 < 32 then
            st1[i1] := ' '
          else
            st1[i1] := K2[i3-31] ;
        end ;
        st1 := trim(st1) ;
        st1 := stringReplace (st1,'  ',' ', [rfReplaceAll,rfIgnoreCase]) ;
        st1 := stringReplace (st1,'_','', [rfReplaceAll,rfIgnoreCase]) ;
      end;
     
    begin
      result := True;
      form1.caption := st_table ;
      try
        // DEBUT
        st_TbSQL := Copy(st_table, 1, Pos('.', st_table)-1);
        Tb := TTable.Create(nil);
        Tb.DatabaseName := st_chemin;
        Tb.TableName := st_table;
        Tb.Exclusive := True;
        Tb.Open;
        // copie des données
        if Tb.RecordCount > 0 then
        begin
          Memo1.Lines.Add(TimeToStr(now) + #9 + 'Nbr Enregistrements dans '+st_TbSQL+' : ' + inttostr(Tb.RecordCount));
          Application.ProcessMessages ;  Sleep (1000) ;
          sl_SQL.Clear ;
          Tb.First;
          while (not Tb.Eof) do
          begin
            st_tmp2 := '';
            for i := 0 to (Tb.Fields.Count - 1) do
            begin
              if not (Tb.Fields[i].DataType in [ftSmallint, ftInteger, ftFloat, ftCurrency]) then
              begin
                if Tb.Fields[i].DataType in [ftDate, ftTime, ftDateTime ] then
                begin
                  st1 := DateToStr(Tb.Fields[i].AsDateTime)  ;
                end
                else
                begin
                  st1 := stringReplace (Tb.Fields[i].AsString,';','-',[rfReplaceAll]) ;
                  if (pos ('ETB',uppercase(st_table))>0) then
                    if (Uppercase(Tb.Fields[i].FieldName) <> Uppercase('EmailEtb')) then
                      ConvertirChaine(st1)
                    else
                      ConvertirChaineEmail(st1) ;
                end ;
                st_tmp2 := st_tmp2 + st1 + ';'
              end
              else
              begin
                if trim(Tb.Fields[i].AsString) = '' then
                  st_tmp2 := st_tmp2 + '0;'
                else
                  if (Tb.Fields[i].DataType in [ftSmallint, ftInteger]) then
                    st_tmp2 := st_tmp2 + StringReplace(Tb.Fields[i].AsString, ',', '.', []) + ';'
                  else
                  begin
                    st2 :=  format ('%1.3f',[Tb.Fields[i].AsFloat]) ;
                    st_tmp2 := st_tmp2 + StringReplace(st2, ',', '.', []) + ';'
                  end;
              end;
            end;
            delete(st_tmp2, length(st_tmp2), 1); // retraît dernière virgule
            sl_SQL.Add(st_tmp2);
            Tb.Next;
          end;
        end;
        // FIN
        Tb.Close;
        Tb.Exclusive := False;
        Tb.Free;
        sl_SQL.SaveToFile('C:\temp\tmp1.csv');
        ExecuterSQL ('BULK INSERT '+st_TbSQL+' FROM ''C:\temp\tmp1.csv''WITH ( MAXERRORS = 0, FIELDTERMINATOR ='';'')',true) ;
        // vérification
        SQLQuery2.SQL.Text := 'select count(*) from '+st_TbSQL;
        SQLQuery2.Open ;
        Memo1.Lines.Add(TimeToStr(now) + #9 + 'Nbr Enregistrements transmis  : ' + SQLQuery2.Fields[0].AsString);
        Application.ProcessMessages ;
        SQLQuery2.Close ;
      except
      end;
     
    end;
     
    Procedure TForm1.ExecuterSQL(st1 : string; b1 : boolean) ;
    begin
      SQLQuery1.SQL.Text := st1 ;
      SQLQuery1.ExecSQL (true) ;
      SQLQuery1.Close ;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    const
      FichierLog = 'ImportDonnees.log';
    var
      sl_sql, sl_PbSQL : TStringList;
      st_chemin : string;
      SR : TSearchRec;
      b_ok : boolean;
    begin
      HANDIC1.Open ;
      Screen.Cursor := crHourGlass;
     
      sl_PbSQL := TStringList.Create;
     
      Memo1.Lines.Add('***************************************************************');
      Memo1.Lines.Add('************ ' + DateTimeToStr(now) + ' -- Début d''import ************');
      Application.ProcessMessages ;
     
      st_chemin := Edit1.Text;
      sl_SQL := TStringList.Create;
      b_ok := True;
     
      // préparation de la base
      PreparationBase (sl_SQL) ;
      ExecuterSQL(sl_SQL.text,true) ;
      // création de la base (suppression si les tables existent et création)
      if FindFirst(st_chemin + '\*.db', faAnyFile, SR) = 0 then  // 0 = trouvé
      begin
        if b_ok and not ImportStructureParadoxVersSQLServer(sl_SQL,  st_chemin, SR.Name) then b_ok := False;
        while FindNext(SR) = 0 do
          if b_ok and not ImportStructureParadoxVersSQLServer(sl_SQL,  st_chemin, SR.Name) then b_ok := False;
        FindClose(SR);
      end ;
      ExecuterSQL(sl_SQL.text,true) ;
     
      if b_ok then
      begin
        if FindFirst(st_chemin + '\*.db', faAnyFile, SR) = 0 then  // 0 = trouvé
        begin
          if b_ok and not ImportDonneesParadoxVersSQLServer1(sl_SQL, sl_PbSQL, st_chemin, SR.Name) then b_ok := False;
          while FindNext(SR) = 0 do
            if b_ok and not ImportDonneesParadoxVersSQLServer1(sl_SQL, sl_PbSQL, st_chemin, SR.Name) then b_ok := False;
          FindClose(SR);
        end;
      end;
     
     
     
      // sauvegarde du fichier log
      Memo1.Lines.Add('');
      Memo1.Lines.Add('************* ' + DateTimeToStr(now) + ' -- Fin d''import *************');
      Memo1.Lines.Add('***************************************************************');
      Application.ProcessMessages ;
     
     
      sl_sql.Free;
      sl_PbSQL.Free;
     
      Screen.Cursor := crDefault;
      HANDIC1.Close ;
    end;
    end.

  12. #12
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2011
    Messages : 63
    Points : 44
    Points
    44
    Par défaut
    Bonjour et merci à tous pour vos réponses, je vais essayer ta solution ShaiLeTroll, j'espère que le test sera concluant et que ça n'alourdira pas la machine. J'aimerai, cependant que vous jetiez un œil sur cette requête que j'ai utilisé pour importer le contenu d'un fichier dbase directement dans une table sql server, ça serait beaucoup plus simple, un timer sous delphi qui exécute cette requête et puis c'est bon mais ça ne marche pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT * into NomTableSQL
    FROM OPENROWSET('MSDASQL', 'Driver=Microsoft Visual FoxPro Driver;
    SourceDB=C:\Users\akournane\Desktop\Mirroir\Test.dbf;
    SourceType=DBF',
    'SELECT * FROM NomTableDBase')
    Voici le message d'erreur que je reçois :

    Le fournisseur OLE DB "MSDASQL" du serveur lié "(null)" a retourné le message "[Microsoft][Gestionnaire de pilotes ODBC] Le pilote ne prend pas cette fonction en charge".
    Msg 7303, Niveau 16, État 1, Ligne 1
    Impossible d'initialiser l'objet de la source de données du fournisseur OLE DB "MSDASQL" du serveur lié "(null)".

    je pense que le problème de 'Microsoft Visual FoxPro Driver', mais je ne sais pas comment faire pour y remédier et quel driver installer. Je travaille avec Microsoft sql server 2005 et sous windows 7 32 bits. A votre avis, qu'est ce qui cloche ?

  13. #13
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 029
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 029
    Points : 40 927
    Points
    40 927
    Billets dans le blog
    62
    Par défaut
    tu n'es pas le seul http://stackoverflow.com/questions/5...-in-sql-server
    et cela semble venir d'un problème de driver ODBC et/ou d'installation
    mais cela n'a plus rien à voir avec la question de départ et DELPHI
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  14. #14
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2011
    Messages : 63
    Points : 44
    Points
    44
    Par défaut
    Il n'y a pas d'erreur de syntaxe, j'ai analysé la requête, j'ai eu "Commande réussie" comme réponse. Donc c'est autre chose.

  15. #15
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2011
    Messages : 63
    Points : 44
    Points
    44
    Par défaut
    Oui, c'était juste une solution alternative au problème. Je suis entrain de tester le code que m'a donné ShaiLeTroll

Discussions similaires

  1. Réponses: 2
    Dernier message: 16/07/2008, 22h32
  2. Changer le séparateur d'un fichier csv depuis VB5
    Par manue22 dans le forum Macros et VBA Excel
    Réponses: 19
    Dernier message: 09/11/2007, 09h29
  3. [CSV] Créer un fichier csv depuis php
    Par jbidou88 dans le forum Langage
    Réponses: 5
    Dernier message: 07/05/2007, 17h41
  4. [CSV] Détecter le séparateur pour les fichiers CSV
    Par JavaEli dans le forum Langage
    Réponses: 1
    Dernier message: 30/11/2005, 23h42
  5. [Excel] séparateur pour les fichiers csv
    Par drinkmilk dans le forum Excel
    Réponses: 2
    Dernier message: 27/08/2005, 14h21

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