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

Delphi Discussion :

Transformer un état en excel sur delphi 7


Sujet :

Delphi

  1. #1
    Membre actif
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2021
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2021
    Messages : 65
    Par défaut Transformer un état en excel sur delphi 7
    Bonjour, je veux connaître comment transférer un état d'impression créer et calculée en parcourant un Tclientdataset sur delphi7 en fichier excel, et comment créer le chemin de sauvegarde de ce fichier
    Merci

  2. #2
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 568
    Billets dans le blog
    65
    Par défaut
    J'aurais une remarque : pourquoi repartir de l'état quand vous avez le Dataset ?
    Une question : avec quel générateur l'état a t-il été créé, certains proposant des exports ?

    Une fois ces questions répondues, est-ce que le(s) poste(s) utilisateur(s) contiennent des versions d'Excel pour pouvoir utiliser Ole ?
    Dans le cas contraire il va falloir trouver des composants tiers par exemple SMExport de Scalabium qui est d'un coût modéré.
    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

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 982
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 982
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Dans le cas contraire il va falloir trouver des composants tiers par exemple SMExport de Scalabium qui est d'un coût modéré.
    Je confirme, je l'utilise dans un projet, on a même modifié le source de la lib pour gérer au plus bas niveau une gestion de doublon de chaine
    Pas cher et si utilisé industriellement, c'est rentable

    En D7, j'ai utilisé TFlexCelImport mais il ne mettait à jour les formules, fallait le réouvrir dans Excel, je ne sais plus si SMExport a le même comportement
    Pour remettre les résultats des formules à niveau voir FinalizeExcelFile issu du sujet c++ builder 2007 + ole excel


    Si tu veux une base de travail TSLTExcelDataSetExporter issu du sujet [D7]Exporter le résultat d'une requête vers Excel cela demandera un peu de travail pour le repasser en D7 mais tu verras que cela n'a rien d'extraordinaire pour un simple export

    Une version plus ancienne de TSLTExcelDataSetExporter issu du sujet Delphi 7 : Créer ou modifier un fichier Excel 2003 sans ouvrir une fenetre Excel qui semble plus facile à migrer mais surement, il n'y a pas la progression pour génération un peu longue

    une astuce, c'est BEAUCOUP plus rapide que manipuler Excel en OLE
    Exporter le Data vers un CSV, puis utiliser Excel pour convertir le CSV en XLSX comme dans une version plus récente de TSLTExcelDataSetExporter qui me semble plus difficile à reporter en D7 mais SaveIntoExcel est bien plus rapide que ViewInExcel

    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
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    557
    558
    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    580
    581
    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    637
    638
    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    654
    655
    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    671
    672
    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    692
    693
    694
    695
    696
    697
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    710
    711
    712
    713
    714
    715
    716
    717
    718
    719
    720
    721
    722
    723
    724
    725
    726
    727
    728
    729
    730
    731
    732
    733
    734
    735
    736
    737
    738
    739
    740
    741
    742
    743
    744
    745
    746
    747
    748
    749
    750
    751
    752
    753
    754
    755
    756
    757
    758
    759
    760
    761
    762
    763
    764
    765
    766
    767
    768
    769
    770
    771
    772
    773
    774
    775
    776
    777
    778
    779
    780
    781
    782
    783
    784
    785
    786
    787
    788
    789
    790
    791
    792
    793
    794
    795
    796
    797
    798
    799
    800
    801
    802
    803
    804
    805
    806
    807
    808
    809
    810
    811
    812
    813
    814
    815
    816
    817
    818
    819
    820
    821
    822
    823
    824
    825
    826
    827
    828
    829
    830
    831
    832
    833
    834
    835
    836
    837
    838
    839
    840
    841
    842
    843
    844
    845
    846
    847
    848
    849
    850
    851
    852
    853
    854
    855
    856
    857
    858
    859
    860
    861
    862
    863
    864
    865
    866
    867
    868
    869
    870
    871
    872
    873
    874
    875
    876
    877
    878
    879
    880
    881
    882
    883
    884
    885
    886
    887
    888
    889
    890
    891
    892
    893
    894
    895
    896
    897
    898
    899
    900
    901
    902
    903
    904
    905
    906
    907
    908
    909
    910
    911
    912
    913
    914
    915
    916
    917
    918
    919
    920
    921
    922
    923
    924
    925
    926
    927
    928
    929
    930
    931
    932
    933
    934
    935
    936
    937
    938
    939
    940
    941
    942
    943
    944
    945
    946
    947
    948
    949
    950
    951
    952
    953
    954
    955
    956
    957
    958
    959
    960
    961
    962
    963
    964
    965
    966
    967
    968
    969
    970
    971
    972
    973
    974
    975
    976
    977
    978
    979
    980
    981
    982
    983
    984
    985
    986
    987
    988
    989
    990
    991
    992
    993
    994
    995
    996
    997
    998
    999
    1000
    1001
    1002
    1003
    1004
    1005
    1006
    1007
    1008
    1009
    1010
    1011
    1012
    1013
    1014
    1015
    1016
    1017
    1018
    1019
    1020
    1021
    1022
    1023
    1024
    1025
    1026
    1027
    1028
    1029
    1030
    1031
    1032
    1033
    1034
    1035
    1036
    1037
    1038
    1039
    1040
    1041
    1042
    1043
    1044
    1045
    1046
    1047
    1048
    1049
    1050
    1051
    1052
    1053
    1054
    1055
    1056
    1057
    1058
    1059
    1060
    1061
    1062
    1063
    1064
    1065
    1066
    1067
    1068
    1069
    1070
    1071
    1072
    1073
    1074
    1075
    1076
    1077
    1078
    1079
    1080
    1081
    1082
    1083
    1084
    1085
    1086
    1087
    1088
    1089
    1090
    1091
    1092
    1093
    1094
    1095
    1096
    1097
    1098
    1099
    1100
    1101
    1102
    1103
    1104
    1105
    1106
    1107
    //------------------------------------------------------------------------------
    (*                SoLuTions is an Versatile Library for Delphi                 -
     *                                                                             -
     *  Version alternative publiée sur "www.developpez.net"                       -
     *  Post : "c++ builder 2007 + ole excel"                                      -
     *  Post Number : 5628011                                                      -
     *  Post URL = "http://www.developpez.net/forums/d1006909/c-cpp/outils-c-cpp/cppbuilder/cpp-builder-2007-p-ole-excel/#post5628011"
     *                                                                             -
     *  Version alternative publiée sur "www.developpez.net"                       -
     *  Post : "excel et delphi"                                                   -
     *  Post Number : 6375536                                                      -
     *  Post URL = "http://www.developpez.net/forums/d1158956/environnements-developpement/delphi/debutant/excel-delphi/#post6375536"
     *                                                                             -
     *  Copyright "SLT Solutions", (©2006)                                         -
     *  contributeur : ShaiLeTroll (2012) - Renommage Fichier et Correction XE2    -
     *  contributeur : ShaiLeTroll (2012) - Documentation Insight                  -
     *  contributeur : ShaiLeTroll (2014) - Reprise de la SLT<2012> sous C++Builder XE2/XE3 vers la SLT<2013> sous Delphi XE2
     *                                                                             -
     *                                                                             -
     * Ce logiciel est un programme informatique servant à aider les développeurs  -
     * Delphi avec une bibliothèque polyvalente, adaptable et fragmentable.        -
     *                                                                             -
     * Ce logiciel est régi par la licence CeCILL-C soumise au droit français et   -
     * respectant les principes de diffusion des logiciels libres. Vous pouvez     -
     * utiliser, modifier et/ou redistribuer ce programme sous les conditions      -
     * de la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA    -
     * sur le site "http://www.cecill.info".                                       -
     *                                                                             -
     * En contrepartie de l'accessibilité au code source et des droits de copie,   -
     * de modification et de redistribution accordés par cette licence, il n'est   -
     * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,   -
     * seule une responsabilité restreinte pèse sur l'auteur du programme,  le     -
     * titulaire des droits patrimoniaux et les concédants successifs.             -
     *                                                                             -
     * A cet égard  l'attention de l'utilisateur est attirée sur les risques       -
     * associés au chargement,  à l'utilisation,  à la modification et/ou au       -
     * développement et à la reproduction du logiciel par l'utilisateur étant      -
     * donné sa spécificité de logiciel libre, qui peut le rendre complexe à       -
     * manipuler et qui le réserve donc à des développeurs et des professionnels   -
     * avertis possédant  des  connaissances  informatiques approfondies.  Les     -
     * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du      -
     * logiciel à leurs besoins dans des conditions permettant d'assurer la        -
     * sécurité de leurs systèmes et ou de leurs données et, plus généralement,    -
     * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.          -
     *                                                                             -
     * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez      -
     * pris connaissance de la licence CeCILL-C, et que vous en avez accepté les   -
     * termes.                                                                     -
     *                                                                             -
     *----------------------------------------------------------------------------*)
    unit SLT.Common.Office.Excel;
     
    interface
     
    uses System.SysUtils, System.Classes, System.Variants, System.Types,
      Vcl.Dialogs, Vcl.ComCtrls,
      Data.DB;
     
    type
      { Forward class declarations }
      TSLTExcelDataSetExporter = class;
      TSLTExcelListViewer = class;
      ISLTXLSReader = interface;
      ISLTXLSFormatSpecification = interface;
      TSLTXLSReader = class;
     
      /// <summary>Erreur de base liée à la création d'un classeur excel à partir d'un TDataSet</summary>
      ESLTExcelDataSetExporterError = class(Exception);
     
      /// <summary>Création d'un classeur excel à partir d'un TDataSet</summary>
      TSLTExcelDataSetExporter = class(TObject)
      public
        type
          TProgressInfo = record
            Position: Integer;
          end;
      private
        // Membres privés
        FDataSet: TDataSet;
        FOnProgress: TNotifyEvent;
        FOnBeforeActivateExcel: TNotifyEvent;
        FCellWithBorder: Boolean;
        FShowWaitMessage: Boolean;
        FProgressInfo: TProgressInfo;
        FHeader: TDataSet;
        FFooter: TDataSet;
     
        // Méthodes privées - Evenement
        procedure DoProgress(APosition: Integer);
        procedure DoBeforeActivateExcel();
     
        // Méthodes privées - Génération Excel
        procedure RenderTitles(const ATitles: array of string; var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
        procedure RenderRows(ADataSet: TDataSet; const AFieldsNames: array of string; var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
        procedure RenderRow(ADataSet: TDataSet; const AFieldsNames: array of string; var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
        procedure RenderTitleWithBorder(var AMSCellItem: OleVariant);
        procedure RenderColumnWithBorder(var AMSCellItem: OleVariant);
        procedure RenderHeader(var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
        procedure RenderFooter(var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
        procedure RenderExtraDataSet(ADataSet: TDataSet; var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
      public
        // Constructeurs
        constructor Create(ADataSet: TDataSet);
     
        // Méthodes publiques
        procedure ViewInExcel(const ASheetName: string; const AFieldsNames, ATitles: array of string);
        procedure SaveIntoExcel(const AExcelFileName: TFileName; const ASheetName: string; const AFieldsNames, ATitles: array of string);
     
        // Propriétés publiques
        property CellWithBorder: Boolean read FCellWithBorder write FCellWithBorder;
        property ProgressInfo: TProgressInfo read FProgressInfo;
        property ShowWaitMessage: Boolean read FShowWaitMessage write FShowWaitMessage;
     
        property Header: TDataSet read FHeader write FHeader;
        property Footer: TDataSet read FFooter write FFooter;
     
        // Évènements publiques
        property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
        property OnBeforeActivateExcel: TNotifyEvent read FOnBeforeActivateExcel write FOnBeforeActivateExcel;
      end;
     
      /// <summary>Erreur de base liée à la création d'un classeur excel à partir d'un TListView</summary>
      ESLTExcelListViewerError = class(Exception);
     
      /// <summary>Création d'un classeur excel à partir d'un TListView</summary>
      TSLTExcelListViewer = class(TObject)
      public
        type
          TProgressInfo = record
            Position: Integer;
            Count: Integer;
          end;
      private
        // Membres privés
        FListView: TListView;
        FOnProgress: TNotifyEvent;
        FOnBeforeActivateExcel: TNotifyEvent;
        FCheckedOnly: Boolean;
        FShowWaitMessage: Boolean;
        FProgressInfo: TProgressInfo;
     
        // Méthodes privées - Evenement
        procedure DoProgress(APosition: Integer; ACount: Integer = -1);
        procedure DoBeforeActivateExcel();
      public
        // Constructeurs
        constructor Create(AListView: TListView);
     
        // Méthodes publiques
        procedure ViewInExcel(const ASheetName: string; const AColumnTypes: array of TVarType);
     
        // Propriétés publiques
        property CheckedOnly: Boolean read FCheckedOnly write FCheckedOnly;
        property ProgressInfo: TProgressInfo read FProgressInfo;
        property ShowWaitMessage: Boolean read FShowWaitMessage write FShowWaitMessage;
     
        // Évènements publiques
        property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
        property OnBeforeActivateExcel: TNotifyEvent read FOnBeforeActivateExcel write FOnBeforeActivateExcel;
      end;
     
     
      /// <summary>Erreur de base liée au fichier XLS</summary>
      ESLTXLSError = class(Exception);
      /// <summary>Erreur de base liée à lecture de fichier XLS</summary>
      ESLTXLSReaderError = class(ESLTXLSError);
      /// <summary>Erreur de base liée à la génération de fichier XLS</summary>
      ESLTXLSWriterError = class(ESLTXLSError);
     
      /// <summary>Cette interface défini les prototypes nécessaires à lecture d'un fichier XLS</summary>
      ISLTXLSReader = interface
        ['{66E9D4BB-5EAB-4642-8A31-6C3E7721167B}']
     
        // Méthodes
        procedure Open();
        procedure Close();
        function ReadNextLine(out AXLSLine: TStringDynArray): Boolean;
        procedure Next();
     
        // Accesseurs
        function GetFileName(): TFileName;
        procedure SetFileName(const Value: TFileName);
        function GetFormatSpecification(): ISLTXLSFormatSpecification;
        function GetEOF(): Boolean;
     
        // Propriétés
        /// <summary>Source des données à lire en format XLS</summary>
        property FileName: TFileName read GetFileName write SetFileName;
        /// <summary>Spécifications de format d'un fichier XLS/summary>
        property FormatSpecification: ISLTXLSFormatSpecification read GetFormatSpecification;
        /// <summary>Détermine si la position en cours du pointeur se trouve en fin de fichier XLS</summary>
        property EOF: Boolean read GetEOF;
      end;
     
      /// <summary>Cette interface défini les prototypes nécessaires fournissant les spécifications de format d'un fichier XLS</summary>
      ISLTXLSFormatSpecification = interface
        ['{3B736580-8294-48BB-A841-AB81E053F891}']
     
        // Accesseurs
        function GetExpectedSheetName(): string;
        procedure SetExpectedSheetName(const Value: string);
        function GetExpectedColumnCount(): Integer;
        procedure SetExpectedColumnCount(const Value: Integer);
     
        // Propriétés
        /// <summary>Nom de la feuille attendue dans le fichier Excel</summary>
        property ExpectedSheetName: string read GetExpectedSheetName write SetExpectedSheetName;
        /// <summary>Nombre de colonnes attendues</summary>
        property ExpectedColumnCount: Integer read GetExpectedColumnCount write SetExpectedColumnCount;
      end;
     
      TSLTXLSReader = class(TInterfacedObject, ISLTXLSReader, ISLTXLSFormatSpecification)
      private
        // Membres Privés - Propriétés
        FFileName: TFileName;
        FExpectedColumnCount: Integer;
        FExpectedSheetName: string;
        FExcelOLE: OLEVariant;
        FExcelOLEWorkbook: OLEVariant;
        FExcelOLEWorkSheet: OLEVariant;
        FExcelOLEWorkRows: OLEVariant;
        FRow: Integer;
     
      public
        // Accesseurs - Implémentation de ISLTXLSReader
        function GetFileName(): TFileName;
        procedure SetFileName(const Value: TFileName);
        function GetFormatSpecification(): ISLTXLSFormatSpecification;
        function GetEOF(): Boolean;
     
        // Accesseurs - Implémentation de ISLTXLSFormatSpecification
        function GetExpectedSheetName(): string;
        procedure SetExpectedSheetName(const Value: string);
        function GetExpectedColumnCount(): Integer;
        procedure SetExpectedColumnCount(const Value: Integer);
     
        // Méthodes - Implémentation de ISLTXLSReader
        procedure Open();
        procedure Close();
        function ReadNextLine(out AXLSLine: TStringDynArray): Boolean;
        procedure Next();
      public
        // Constructeurs
        constructor Create();
        destructor Destroy(); override;
      end;
     
    implementation
     
    uses Winapi.Windows, System.Win.ComObj, System.UITypes, System.Math, System.IOUtils,
      SLT.Common.StrUtilsEx, SLT.Common.Winapi.ShellApi,
      SLT.Controls.VCL.DialogsEx;
     
    { procedural code forward declarations }
     
    /// <summary>Equivalent de SetForegroundWindow avec un délai retardant la mise au premier plan, cela laisse le temps d'afficher le TSLTMessageDlg </summary>
    procedure SetForegroundWindowAsync(const AWindowExcelCaption: string; Delay: Cardinal = INFINITE); forward;
     
    { TSLTExcelDataSetExporter }
     
    //------------------------------------------------------------------------------
    constructor TSLTExcelDataSetExporter.Create(ADataSet: TDataSet);
    begin
      inherited Create();
     
      FDataSet := ADataSet;
      FShowWaitMessage := True;
     
      if not Assigned(FDataSet) then
        raise ESLTExcelDataSetExporterError.Create('Aucune donnée disponible pour la Visualisation sous Excel !');
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.DoBeforeActivateExcel();
    begin
      if Assigned(FOnBeforeActivateExcel) then
        FOnBeforeActivateExcel(Self);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.DoProgress(APosition: Integer);
    begin
      FProgressInfo.Position := APosition;
      if Assigned(FOnProgress) then
        FOnProgress(Self);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.RenderColumnWithBorder(var AMSCellItem: OleVariant);
    const
      xlEdgeBottom = $00000009;
      xlEdgeLeft = $00000007;
      xlEdgeRight = $0000000A;
      xlEdgeTop = $00000008;
      xlInsideHorizontal = $0000000C;
      xlInsideVertical = $0000000B;
    begin
      AMSCellItem.Borders[xlEdgeRight].LineStyle := 1;
      AMSCellItem.Borders[xlEdgeRight].Weight := 2;
      AMSCellItem.Borders[xlEdgeLeft].LineStyle := 1;
      AMSCellItem.Borders[xlEdgeLeft].Weight := 2;
      AMSCellItem.Borders[xlEdgeBottom].LineStyle := 1;
      AMSCellItem.Borders[xlEdgeBottom].Weight := 2;
      AMSCellItem.Borders[xlEdgeTop].LineStyle := 1;
      AMSCellItem.Borders[xlEdgeTop].Weight := 2;
      AMSCellItem.Borders[xlInsideVertical].LineStyle := 1;
      AMSCellItem.Borders[xlInsideVertical].Weight := 2;
      AMSCellItem.Borders[xlInsideHorizontal].LineStyle := 1;
      AMSCellItem.Borders[xlInsideHorizontal].Weight := 2;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.RenderTitleWithBorder(var AMSCellItem: OleVariant);
    const
      xlEdgeBottom = $00000009;
      xlEdgeLeft = $00000007;
      xlEdgeRight = $0000000A;
      xlEdgeTop = $00000008;
    begin
      AMSCellItem.Borders[xlEdgeRight].LineStyle := 1;
      AMSCellItem.Borders[xlEdgeRight].Weight := 3;
      AMSCellItem.Borders[xlEdgeLeft].LineStyle := 3;
      AMSCellItem.Borders[xlEdgeLeft].Weight := 3;
      AMSCellItem.Borders[xlEdgeBottom].LineStyle := 1;
      AMSCellItem.Borders[xlEdgeBottom].Weight := 3;
      AMSCellItem.Borders[xlEdgeTop].LineStyle := 1;
      AMSCellItem.Borders[xlEdgeTop].Weight := 3;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.RenderExtraDataSet(ADataSet: TDataSet; var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
    var
      FieldsNames, Titles: array of string;
      I, L: Integer;
    begin
      L := ADataSet.FieldCount;
      SetLength(FieldsNames, L);
      SetLength(Titles, L);
      for I := 0 to L - 1 do
      begin
        FieldsNames[I] := ADataSet.Fields[I].FieldName;
        Titles[I] := ADataSet.Fields[I].DisplayName;
      end;
     
      RenderTitles(Titles, ARow, AExcelOLEWorkSheet);
      RenderRows(ADataSet, FieldsNames, ARow, AExcelOLEWorkSheet);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.RenderFooter(var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
    begin
      if Assigned(FFooter) then
        RenderExtraDataSet(FFooter, ARow, AExcelOLEWorkSheet);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.RenderHeader(var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
    begin
      if Assigned(FHeader) then
        RenderExtraDataSet(FHeader, ARow, AExcelOLEWorkSheet);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.RenderRow(ADataSet: TDataSet; const AFieldsNames: array of string; var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
    var
      I: Integer;
      Field: TField;
      ExcelOLEWorkSheetCell: OLEVariant;
    begin
      for I := Low(AFieldsNames) to High(AFieldsNames) do
      begin
        Field := ADataSet.FieldByName(AFieldsNames[I]);
        ExcelOLEWorkSheetCell := AExcelOLEWorkSheet.Cells[ARow, I + 1];
     
        // FormulaLocal utilise les options régionales pour traduire une valeur,
        // cela gère ainsi le séparateur décimal correctement
        if Field.DataType = ftFloat then
          ExcelOLEWorkSheetCell.FormulaLocal := Field.AsString
        // cela gère ainsi le format de date français correctement
        else if Field.DataType in [ftDate, ftDateTime, ftTime] then
          ExcelOLEWorkSheetCell.FormulaLocal := Field.AsString
        // Force une chaine ce qui évite la perte des Zéros au début sur une chaine ressemblant à un nombre comme un Code-Barre
        else if Field.DataType = ftString then
          ExcelOLEWorkSheetCell.Formula := Field.AsString
        // Les autres données sont recopiées brutes
        else
          ExcelOLEWorkSheetCell.Value := Field.AsString;
      end;
      Inc(ARow);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.RenderRows(ADataSet: TDataSet; const AFieldsNames: array of string; var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
    var
      Bookmark: TBookmark;
    begin
      ADataSet.DisableControls();
      try
        Bookmark := ADataSet.Bookmark;
        try
          ADataSet.First();
          while not ADataSet.EOF do
          begin
            RenderRow(ADataSet, AFieldsNames, ARow, AExcelOLEWorkSheet);
     
            ADataSet.Next();
     
            // Patience tout les 16 lignes, c'est suffisant !
            if not ByteBool(ARow and $0F) then
              DoProgress(ARow);
          end;
     
        finally
          ADataSet.Bookmark := Bookmark;
        end;
      finally
        ADataSet.EnableControls();
      end;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.RenderTitles(const ATitles: array of string; var ARow: Integer; AExcelOLEWorkSheet: OLEVariant);
    var
      I: Integer;
      ExcelOLEWorkSheetCell: OLEVariant;
    begin
      for I := Low(ATitles) to High(ATitles) do
      begin
        ExcelOLEWorkSheetCell := AExcelOLEWorkSheet.Cells[ARow, I + 1];
        ExcelOLEWorkSheetCell.Value := ATitles[I];
        if CellWithBorder or Assigned(FHeader) or Assigned(FFooter) then
          RenderTitleWithBorder(ExcelOLEWorkSheetCell);
      end;
      Inc(ARow);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.SaveIntoExcel(const AExcelFileName: TFileName; const ASheetName: string; const AFieldsNames, ATitles: array of string);
     
      //--------------------------------------------------------------------------
      function WriteDataIntoTabSeparatedTextFile(ADataSet: TDataSet; const ATempFileName: TFileName): Integer;
      var
        lCSVLine: TStringDynArray;
        lCSVLineText: AnsiString;
        lCSVStream: TFileStream;
        I: Integer;
        Field: TField;
      begin
        Result := 0;
        if Assigned(ADataSet) and not ADataSet.IsEmpty then
        begin
          lCSVStream := TFileStream.Create(ATempFileName, fmCreate);
          try
            SetLength(lCSVLine, Length(ATitles));
            for I := Low(ATitles) to High(ATitles) do
              lCSVLine[I] := ATitles[I];
            lCSVLineText := AnsiString(SLT.Common.StrUtilsEx.ImplodeLazy(lCSVLine, Tabulator)) + sLineBreak;
            lCSVStream.WriteBuffer(lCSVLineText[1], Length(lCSVLineText) * SizeOf(AnsiChar));
            Result := 1;
     
            ADataSet.DisableControls();
            try
              ADataSet.First();
              while not ADataSet.EOF do
              begin
                for I := Low(AFieldsNames) to High(AFieldsNames) do
                begin
                  // Pas de gestion de type dans cette version
                  Field := FDataSet.FieldByName(AFieldsNames[I]);
                  lCSVLine[I] := Field.AsString;
                end;
     
                lCSVLineText := AnsiString(SLT.Common.StrUtilsEx.ImplodeLazy(lCSVLine, Tabulator) + sLineBreak);
                lCSVStream.WriteBuffer(lCSVLineText[1], Length(lCSVLineText) * SizeOf(AnsiChar));
     
                Inc(Result);
     
                // Patience tout les 16 lignes, c'est suffisant !
                if not ByteBool(Result and $0F) then
                  DoProgress(Result);
     
                ADataSet.Next();
              end;
            finally
              ADataSet.EnableControls();
            end;
          finally
            lCSVStream.Free();
          end;
        end;
      end;
     
      //--------------------------------------------------------------------------
      procedure ExcelBringToFront();
      var
        ExcelOLE: OLEVariant;
        ExcelCaption: string;
      begin
        ExcelOLE := System.Win.ComObj.GetActiveOleObject('Excel.Application');
        try
          if not VarIsEmpty(ExcelOLE) then
          begin
            ExcelOLE.Visible := True;
            ExcelCaption := ExcelOLE.Caption;
            // Affiche l'excel lancé !
            SetForegroundWindow(FindWindow(nil, PChar(ExcelCaption)));
          end;
        finally
          ExcelOLE := Unassigned;
        end;
      end;
     
      //--------------------------------------------------------------------------
      /// <seealso href="http://www.developpez.net/forums/d1006909/c-cpp/outils-c-cpp/cppbuilder/cpp-builder-2007-p-ole-excel/#post5628011">Source originale déposée sous mon pseudo ShaiLeTroll présent dans "c++ builder 2007 + ole excel"</seealso>
      /// <seealso href="http://www.developpez.net/forums/d1158956/environnements-developpement/delphi/debutant/excel-delphi/#post6375536">Source alternative déposée sous mon pseudo ShaiLeTroll présent dans "excel et delphi "</seealso>
      /// <seealso href="http://www.rondebruin.nl/mac/mac020.htm">SaveAs and FileFormat numbers</seealso>
      /// <seealso href="http://www.rondebruin.nl/win/s5/win001.htm">Use VBA SaveAs in Excel 2007-2013</seealso>
      procedure ConvertToExcel(ATempFileName: TFileName; ARowCount: Integer);
      const
        // constantes de XlFileFormat
        Excel2000WorkbookNormal = $FFFFEFD1; // ou -4143 - xlWorkbookNormal : dépend de la version
        Excel2007Excel8 = 56; // xlExcel8 : 97-2003 format in Excel 2007-2013, xls
        Excel2007OpenXMLWorkbook = 51; // xlOpenXMLWorkbook : Open XML Workbook in Excel 2007-2013, xlsx
        Excel2007Version = '12';
      var
        ExcelOLE: OLEVariant;
        ExcelOLEWorkbook: OLEVariant;
        ExcelOLEWorkSheet: OLEVariant;
        ExcelXMLSupported: Boolean;
        FinalizedExcelFileName: TFileName;
      begin
        try
          // Code en LateBinding !
          ExcelOLE := System.Win.ComObj.CreateOleObject('Excel.Application');
          try
            ExcelOLE.UserControl := False;
            ExcelOLE.Visible := False;
            ExcelOLEWorkbook := ExcelOLE.WorkBooks.Open(ATempFileName);
            try
              ExcelOLEWorkSheet := ExcelOLEWorkbook.ActiveSheet;
              ExcelOLEWorkSheet.Name := ASheetName;
              ExcelXMLSupported := SLT.Common.StrUtilsEx.CompareVersion(ExcelOLE.Version, Excel2007Version) >= 0;
     
              if ExcelXMLSupported then
                FinalizedExcelFileName := AExcelFileName
              else
                FinalizedExcelFileName := ChangeFileExt(AExcelFileName, '.xls');
     
              if SameText(ExtractFileExt(FinalizedExcelFileName), '.xls') then
              begin
                if ExcelXMLSupported then
                  ExcelOLEWorkbook.SaveAs(Filename := FinalizedExcelFileName, FileFormat := Excel2007Excel8)
                else
                  ExcelOLEWorkbook.SaveAs(Filename := FinalizedExcelFileName, FileFormat := Excel2000WorkbookNormal)
              end
              else
                ExcelOLEWorkbook.SaveAs(Filename := FinalizedExcelFileName, FileFormat := Excel2007OpenXMLWorkbook);
     
            finally
              ExcelOLEWorkbook.Close(SaveChanges := False);
              ExcelOLEWorkbook := Unassigned;
            end;
          finally
            ExcelOLE.Quit;
            ExcelOLE := Unassigned;
          end;
     
          DoBeforeActivateExcel();
          // Affichage très capricieux
          TSLTShellExecuteWrapper.Execute(FinalizedExcelFileName, nil, 0, SW_SHOWMAXIMIZED);
        except
          on E: Exception do
            raise Exception.CreateFmt('Erreur durant la Consolidation du Fichier Excel %s : %s', [ExtractFileName(AExcelFileName), E.Message]);
        end;
      end;
     
    var
      TempFileName: TFileName;
      RowCount: Integer;
    begin
      DoProgress(0);
     
      try
        if TFile.Exists(AExcelFileName) then
          TFile.Delete(AExcelFileName);
      except
        // Excel possède le fichier et empêche la suppression ?
        on Eioe: EInOutError do
        begin
          MessageDlg(Eioe.Message, mtError, [mbAbort], 0);
          ExcelBringToFront();
          Abort;
        end;
      end;
     
      // Construction d'un fichier texte séparateur tabulation avec virgule selon option régionale
      TempFileName := AExcelFileName + '.tsv'; // Tab-separated values
      RowCount := WriteDataIntoTabSeparatedTextFile(Self.FDataSet, TempFileName);
      if (RowCount > 0) and FileExists(TempFileName) then
      begin
        try
          // Conversion du fichier fichier texte séparateur tabulation en format EXCEL binaire ou Open XML
          ConvertToExcel(TempFileName, RowCount);
        finally
          TFile.Delete(TempFileName);
        end;
      end;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelDataSetExporter.ViewInExcel(const ASheetName: string; const AFieldsNames, ATitles: array of string);
    const
      TEXT_FORMAT: WideString = '@'; // @ indique un texte, le typage en WideString est nécessaire pour qu'Excel le comprenne correctement
    var
      ExcelOLE: OLEVariant;
      ExcelOLEWorkbook: OLEVariant;
      ExcelOLEWorkSheet: OLEVariant;
      ExcelOLEColumn: OLEVariant;
      ExcelCaption: string;
      I, R: Integer;
      Field: TField;
      KeepOpenedExcel: Boolean;
    begin
      Assert(Length(AFieldsNames) = Length(ATitles), 'TSLTExcelDataSetExporter.ViewInExcel : Length(AFieldsNames) <> Length(ATitles)');
     
      DoProgress(0);
     
      KeepOpenedExcel := False;
      try
        // Code en LateBinding !
        ExcelOLE := System.Win.ComObj.CreateOleObject('Excel.Application');
        try
          ExcelOLE.UserControl := False;
          ExcelOLE.Visible := False;
          ExcelOLEWorkbook := ExcelOLE.WorkBooks.Add;
          try
            // Sheets.Item is one-based !
            for I := ExcelOLEWorkbook.Sheets.Count downto 2 do
              ExcelOLEWorkbook.Sheets.Item[I].Delete;
     
            // Le nom d'une feuille Excel est limité à 31 caractères
            ExcelOLEWorkSheet := ExcelOLEWorkbook.Sheets.Item[1];
            ExcelOLEWorkSheet.Name := Copy(ASheetName, 1, 31);
            // Le passage d'un Texte préfixé par ' vers une Formule permet de forcer le typage texte d'un nombre mais en masquant la guillemet !
            // Je génère Excel directement en OLE
     
            // Cells is one-based !
            R := 1;
     
            // Bordures (c'est moins précis que cellule par cellule mais incroyablement plus rapide)
            if FCellWithBorder then
            begin
              for I := Low(ATitles) to High(ATitles) do
              begin
                ExcelOLEColumn := ExcelOLEWorkSheet.Columns[I + 1];
                RenderColumnWithBorder(ExcelOLEColumn);
              end;
            end;
     
            // Copie des titres et données d'un éventuel entête dans les cellules du Excel
            RenderHeader(R, ExcelOLEWorkSheet);
     
            // Copie des titres dans les cellules dans une ligne du Excel
            RenderTitles(ATitles, R, ExcelOLEWorkSheet);
     
            // Columns is one-based !
            for I := Low(AFieldsNames) to High(AFieldsNames) do
            begin
              // Force une chaine ce qui évite la perte des Zéros en début d'un texte, comme un code barre par exemple
              Field := FDataSet.FieldByName(AFieldsNames[I]);
              if Field.DataType = ftString then
                ExcelOLEWorkSheet.Columns[I + 1].NumberFormat := TEXT_FORMAT;
            end;
     
            // Copie du DataSet dans les cellules du Excel
            RenderRows(FDataSet, AFieldsNames, R, ExcelOLEWorkSheet);
     
            // Copie des titres et données d'un éventuel fin-de-page dans les cellules du Excel
            RenderFooter(R, ExcelOLEWorkSheet);
     
            // Redimensionnement des colonnes par rapport aux données + Bordures
            for I := Low(ATitles) to High(ATitles) do
              ExcelOLEWorkSheet.Columns[I + 1].AutoFit;
     
            ExcelOLE.Visible := True;
            ExcelOLE.UserControl := True;
            ExcelCaption := ExcelOLE.Caption;
     
            DoBeforeActivateExcel();
     
            // Affichera l'excel lancé (différé pour éviter que le TSLTMessageDlg reprenne le Focus)
            SetForegroundWindowAsync(ExcelCaption, 100);
     
            // un simple message servira de système d'attente, c'est pauvre mais efficace !
            if FShowWaitMessage then
              KeepOpenedExcel := (TSLTMessageDlg.Show('Excel est ouvert, continuez ...', mtConfirmation, [mbYes, mbNo], ['Fermer Excel', 'Continuer sans fermer Excel']) = mrNo)
            else
              KeepOpenedExcel := True;
     
          finally
            if not VarIsClear(ExcelOLEWorkbook) then
            begin
              if not KeepOpenedExcel then
                ExcelOLEWorkbook.Close(SaveChanges := False);
              ExcelOLEWorkbook := Unassigned;
            end;
          end;
     
        finally
          if not VarIsClear(ExcelOLE) then
          begin
            if not KeepOpenedExcel then
              if ExcelOLE.WorkBooks.Count = 0 then
                ExcelOLE.Quit;
            ExcelOLE := Unassigned;
          end;
        end;
     
      except
        on EOSE: EOleSysError do
          if EOSE.ErrorCode <> RPC_E_DISCONNECTED then
            raise ESLTExcelDataSetExporterError.CreateFmt('Erreur durant la Fermeture de la Visualisation sous Excel : %s', [EOSE.Message]);
        on E: Exception do
          raise ESLTExcelDataSetExporterError.CreateFmt('Erreur durant la Visualisation sous Excel : %s', [E.Message]);
      end;
    end;
     
    { TSLTExcelListViewer }
     
    //------------------------------------------------------------------------------
    constructor TSLTExcelListViewer.Create(AListView: TListView);
    begin
      inherited Create();
     
      FListView := AListView;
      FShowWaitMessage := True;
     
      if not Assigned(FListView) then
        raise ESLTExcelListViewerError.Create('Aucune donnée disponible pour la Visualisation sous Excel !');
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelListViewer.DoBeforeActivateExcel();
    begin
      if Assigned(FOnBeforeActivateExcel) then
        FOnBeforeActivateExcel(Self);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelListViewer.DoProgress(APosition: Integer; ACount: Integer = -1);
    begin
      if ACount > 0 then
        FProgressInfo.Count := ACount;
      FProgressInfo.Position := APosition;
      if Assigned(FOnProgress) then
        FOnProgress(Self);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTExcelListViewer.ViewInExcel(const ASheetName: string; const AColumnTypes: array of TVarType);
    const
      TEXT_FORMAT: WideString = '@'; // @ indique un texte, le typage en WideString est nécessaire pour qu'Excel le comprenne correctement
    var
      ExcelOLE: OLEVariant;
      ExcelOLEWorkbook: OLEVariant;
      ExcelOLEWorkSheet: OLEVariant;
      ExcelCaption: string;
      I, R, Rx: Integer;
      KeepOpenedExcel: Boolean;
    begin
      DoProgress(0, FListView.Items.Count);
     
      KeepOpenedExcel := False;
      try
        // Code en LateBinding !
        ExcelOLE := System.Win.ComObj.CreateOleObject('Excel.Application');
        try
          ExcelOLE.UserControl := False;
          ExcelOLE.Visible := False;
          ExcelOLEWorkbook := ExcelOLE.WorkBooks.Add;
          try
            // Sheets.Item is one-based !
            for I := ExcelOLEWorkbook.Sheets.Count downto 2 do
              ExcelOLEWorkbook.Sheets.Item[I].Delete;
     
            // Le nom d'une feuille Excel est limité à 31 caractères
            ExcelOLEWorkSheet := ExcelOLEWorkbook.Sheets.Item[1];
            ExcelOLEWorkSheet.Name := Copy(ASheetName, 1, 31);
            // Le passage d'un Texte préfixé par ' vers une Formule permet de forcer le typage texte d'un nombre mais en masquant la guillemet !
            // Je génère Excel directement en OLE
     
            // Cells is one-based !
            Rx := 1;
            for I := 0 to FListView.Columns.Count - 1 do
            begin
              ExcelOLEWorkSheet.Cells.Item[Rx, I + 1].Value := FListView.Columns[I].Caption;
     
              // Force une chaine ce qui évite la perte des Zéros en début d'un texte, comme un code barre par exemple
              if (I <= High(AColumnTypes)) and (AColumnTypes[I] = varString) then
                ExcelOLEWorkSheet.Columns[I + 1].NumberFormat := TEXT_FORMAT;
            end;
     
            // Cells is one-based !
            // Les données en deuxieme ligne
            Rx := 2;
            for R := 0 to FListView.Items.Count - 1 do
            begin
              with FListView.Items[R] do
              begin
                // On ajoute soit
                // - c'est tout et pas seulement les cochés (not FCheckedOnly)
                // - les case à cocher ne sont pas activé dans la liste (not FListView.Checkboxes)
                // - on filtre seulement les cochés (Checked)
                if not FCheckedOnly or not FListView.Checkboxes or Checked then
                begin
                  // 1er colonne c'est le texte
                  ExcelOLEWorkSheet.Cells[Rx, 1].Value := Caption;
                  // les colonnes suivantes c'est les sous-texte
                  for I := 0 to SubItems.Count - 1 do
                    ExcelOLEWorkSheet.Cells[Rx, I + 2].FormulaLocal := SubItems[I];
     
                  Inc(Rx);
                end;
              end;
     
              // Patience tout les 16 lignes, c'est suffisant !
              if not ByteBool(R and $0F) then
                DoProgress(R);
            end;
     
            // Redimensionnement des colonnes par rapport aux données
            for I := 0 to FListView.Columns.Count - 1 do
              ExcelOLEWorkSheet.Columns[I + 1].AutoFit;
     
            ExcelOLE.Visible := True;
            ExcelOLE.UserControl := True;
            ExcelCaption := ExcelOLE.Caption;
     
            DoBeforeActivateExcel();
     
            // Affichera l'excel lancé (différé pour éviter que le TSLTMessageDlg reprenne le Focus)
            SetForegroundWindowAsync(ExcelCaption, 100);
     
            // un simple message servira de système d'attente, c'est pauvre mais efficace !
            if FShowWaitMessage then
              KeepOpenedExcel := (TSLTMessageDlg.Show('Excel est ouvert, continuez ...', mtConfirmation, [mbYes, mbNo], ['Fermer Excel', 'Continuer sans fermer Excel']) = mrNo)
            else
              KeepOpenedExcel := True;
     
          finally
            if not VarIsClear(ExcelOLEWorkbook) then
            begin
              if not KeepOpenedExcel then
                ExcelOLEWorkbook.Close(SaveChanges := False);
              ExcelOLEWorkbook := Unassigned;
            end;
          end;
     
        finally
          if not VarIsClear(ExcelOLE) then
          begin
            if not KeepOpenedExcel then
              if ExcelOLE.WorkBooks.Count = 0 then
                ExcelOLE.Quit;
            ExcelOLE := Unassigned;
          end;
        end;
     
      except
        on EOSE: EOleSysError do
          if EOSE.ErrorCode <> RPC_E_DISCONNECTED then
            raise ESLTExcelListViewerError.CreateFmt('Erreur durant la Fermeture de la Visualisation sous Excel : %s', [EOSE.Message]);
        on E: Exception do
          raise ESLTExcelListViewerError.CreateFmt('Erreur durant la Visualisation sous Excel : %s', [E.Message]);
      end;
    end;
     
    { TSLTXLSReader }
     
    //------------------------------------------------------------------------------
    procedure TSLTXLSReader.Close();
    begin
      try
        FExcelOLEWorkSheet := Unassigned;
     
        try
          if not VarIsClear(FExcelOLEWorkbook) then
          begin
            FExcelOLEWorkbook.Close(SaveChanges := False);
            FExcelOLEWorkbook := Unassigned;
          end;
        except
          // On ignore cette erreur !
          FExcelOLEWorkbook := Unassigned;
        end;
     
        if not VarIsClear(FExcelOLE) then
        begin
          if FExcelOLE.WorkBooks.Count = 0 then
            FExcelOLE.Quit;
          FExcelOLE := Unassigned;
        end;
      except
        on EOSE: EOleSysError do
          if EOSE.ErrorCode <> RPC_E_DISCONNECTED then
            raise ESLTXLSReaderError.CreateFmt('Erreur durant la Fermeture du lecteur de fichier Excel : %s', [EOSE.Message]);
        on E: Exception do
          raise ESLTXLSReaderError.CreateFmt('Erreur durant la Fermeture du lecteur de fichier Excel : %s', [E.Message]);
      end;
    end;
     
    //------------------------------------------------------------------------------
    constructor TSLTXLSReader.Create();
    begin
      inherited Create();
     
    end;
     
    //------------------------------------------------------------------------------
    destructor TSLTXLSReader.Destroy();
    begin
      Close();
     
      inherited Destroy();
    end;
     
    //------------------------------------------------------------------------------
    function TSLTXLSReader.GetEOF(): Boolean;
    begin
      Result := FRow >= FExcelOLEWorkRows.Count;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTXLSReader.GetExpectedColumnCount(): Integer;
    begin
      Result := FExpectedColumnCount;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTXLSReader.GetExpectedSheetName(): string;
    begin
      Result := FExpectedSheetName;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTXLSReader.GetFileName(): TFileName;
    begin
      Result := FFileName;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTXLSReader.GetFormatSpecification(): ISLTXLSFormatSpecification;
    begin
      Result := Self;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTXLSReader.Next();
    begin
      Inc(FRow);
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTXLSReader.Open();
     
      function FindFirstSheet(AWorkbook: OleVariant): OleVariant;
      begin
        // Sheets.Item is one-based !
        Result := Unassigned;
        if FExcelOLEWorkbook.Sheets.Count >= 1 then
          Result := FExcelOLEWorkbook.Sheets.Item[1];
      end;
     
      function FindSheet(AWorkbook: OleVariant; const ASheetName: string): OleVariant;
      var
        I: Integer;
      begin
        // Sheets.Item is one-based !
        for I := 1 to FExcelOLEWorkbook.Sheets.Count do
        begin
          Result := FExcelOLEWorkbook.Sheets.Item[I];
          if SameText(Result.Name, ASheetName) then
            Exit;
        end;
     
        Result := Unassigned;
      end;
     
    begin
      FExcelOLEWorkRows := Unassigned;
      FExcelOLEWorkSheet := Unassigned;
      FExcelOLEWorkbook := Unassigned;
      FExcelOLE := Unassigned;
      // Cells is one-based, la première opération de ReadNextLine doit être l'incrémentation de l'indice de ligne FRow  !
      FRow := 0;
     
      try
        // Code en LateBinding !
        FExcelOLE := System.Win.ComObj.CreateOleObject('Excel.Application');
     
        // Excel caché
        FExcelOLE.UserControl := False;
        FExcelOLE.Visible := False;
        FExcelOLEWorkbook := FExcelOLE.WorkBooks.Open(FFileName);
     
        // Recherche de la Feuille
        if FExpectedSheetName <> '' then
        begin
          FExcelOLEWorkSheet := FindSheet(FExcelOLEWorkbook, FExpectedSheetName);
          if VarIsEmpty(FExcelOLEWorkSheet) then
            raise ESLTXLSReaderError.CreateFmt('Erreur durant l''Ouverture du fichier Excel : Feuille "%s" non trouvée', [FExpectedSheetName]);
        end
        else
        begin
          FExcelOLEWorkSheet := FindFirstSheet(FExcelOLEWorkbook);
          if VarIsEmpty(FExcelOLEWorkSheet) then
            raise ESLTXLSReaderError.Create('Erreur durant l''Ouverture du fichier Excel : Aucune feuille trouvée');
        end;
     
        // Obtention des données présentes de la Feuille
        FExcelOLEWorkRows := FExcelOLEWorkSheet.UsedRange.Rows;
     
        if VarIsEmpty(FExcelOLEWorkSheet) then
          raise ESLTXLSReaderError.Create('Erreur durant l''Ouverture du fichier Excel : Aucune donnée trouvée');
      except
        on EOSE: EOleSysError do
          if EOSE.ErrorCode <> RPC_E_DISCONNECTED then
            raise ESLTXLSReaderError.CreateFmt('Erreur durant l''Ouverture du lecteur de fichier Excel : %s', [EOSE.Message]);
        on E: Exception do
          raise ESLTXLSReaderError.CreateFmt('Erreur durant l''Ouverture du lecteur de fichier Excel : %s', [E.Message]);
      end;
    end;
     
    //------------------------------------------------------------------------------
    function TSLTXLSReader.ReadNextLine(out AXLSLine: TStringDynArray): Boolean;
    var
      I, Col, ColCount, OutCount: Integer;
    begin
      Inc(FRow);
     
      ColCount := FExcelOLEWorkRows.Columns.Count;
      // Le nombre de colonne attendu n'est fourni qu'après avoir lu l'entête
      if FExpectedColumnCount > 0 then
        OutCount := FExpectedColumnCount
      else
        OutCount := ColCount;
     
      SetLength(AXLSLine, OutCount);
      for I := Low(AXLSLine) to High(AXLSLine) do
      begin
        // Columns is one-based !
        Col := I + 1;
        if Col <= ColCount then
          AXLSLine[I] := FExcelOLEWorkRows.Cells.Item[FRow, Col];
      end;
     
      Result := True;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTXLSReader.SetExpectedColumnCount(const Value: Integer);
    begin
      FExpectedColumnCount := Value;
    end;
     
     
    //------------------------------------------------------------------------------
    procedure TSLTXLSReader.SetExpectedSheetName(const Value: string);
    begin
      FExpectedSheetName := Value;
    end;
     
    //------------------------------------------------------------------------------
    procedure TSLTXLSReader.SetFileName(const Value: TFileName);
    begin
      FFileName := Value;
    end;
     
    { procedural code declarations }
     
    //------------------------------------------------------------------------------
    procedure SetForegroundWindowAsync(const AWindowExcelCaption: string; Delay: Cardinal = INFINITE);
    begin
      TThread.CreateAnonymousThread(
        procedure
        var
          Tentative: Integer;
          ExcelWnd: HWND;
          ForegroundedExcel: Boolean;
        begin
          Tentative := 0;
          repeat
            if Delay <> INFINITE then
              Sleep(Delay);
     
            ExcelWnd := FindWindow(nil, PChar(AWindowExcelCaption));
            ForegroundedExcel := (SetForegroundWindow(ExcelWnd) or LongBool(SetActiveWindow(ExcelWnd)))
              and (GetForegroundWindow() = ExcelWnd);
     
            Inc(Tentative);
          until ForegroundedExcel or (Tentative > 5);
     
        end).Start();
    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

  4. #4
    Membre actif
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2021
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2021
    Messages : 65
    Par défaut
    Je suis débutante dans ce domaine un lien pour m'expliquer tout et en détail

  5. #5
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    998
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 998

  6. #6
    Membre actif
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2021
    Messages
    65
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2021
    Messages : 65
    Par défaut
    Hhhhhh je lire Delphi help

  7. #7
    Membre Expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 471
    Par défaut
    Bonjour,

    Pour créer le chemin de sauvegarde, c'est tout bête : tu as la fonction ForceDirectories. Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Dir: string;
    begin
      Dir := 'C:\APPS\SALES\LOCAL';
      if ForceDirectories(Dir) then
        Label1.Caption := Dir + ' a été créé'
    end;

  8. #8
    Membre Expert
    Avatar de Charly910
    Homme Profil pro
    Ingénieur TP
    Inscrit en
    Décembre 2006
    Messages
    2 471
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur TP
    Secteur : Bâtiment Travaux Publics

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 471
    Par défaut
    Sinon pour les données d'un Dataset, regarde ici tu trouveras des pistes

    A+
    Charly

  9. #9
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Janvier 2014
    Messages
    132
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2014
    Messages : 132
    Par défaut Transformer un état en excel sur delphi 7
    Bonjour,

    Un lien pour transformer un StringGrid vers Excel

    https://www.developpez.net/forums/d6...id-vers-excel/

    Ça marche

  10. #10
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 526
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 526
    Par défaut
    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
    {
      Exporting a DBGrid to excel without OLE
     
      I develop software and about 95% of my work deals with databases.
      I enjoied the advantages of using Microsoft Excel in my projects
      in order to make reports but recently I decided to convert myself
      to the free OpenOffice suite.
      I faced with the problem of exporting data to Excel without having
      Office installed on my computer.
      The first solution was to create directly an Excel format compatible file:
      this solution is about 50 times faster than the OLE solution but there
      is a problem: the output file is not compatible with OpenOffice.
      I wanted a solution which was compatible with each "DataSet";
      at the same time I wanted to export only the dataset data present in
      a DBGrid and not all the "DataSet".
      Finally I obtained this solution which satisfied my requirements.
      I hope that it will be usefull for you too.
     
      First of all you must import the ADOX type library
      which will be used to create the Excel file and its
      internal structure: in the Delphi IDE:
     
      1)Project->Import Type Library:
      2)Select "Microsoft ADO Ext. for DDL and Security"
      3)Uncheck "Generate component wrapper" at the bottom
      4)Rename the class names (TTable, TColumn, TIndex, TKey, TGroup, TUser, TCatalog) in
        (TXTable, TXColumn, TXIndex, TXKey, TXGroup, TXUser, TXCatalog)
        in order to avoid conflicts with the already present TTable component.
      5)Select the Unit dir name and press "Create Unit".
        It will be created a file named AOX_TLB.
        Include ADOX_TLB in the "uses" directive inside the file in which you want
        to use ADOX functionality.
     
      That is all. Let's go now with the implementation:
    }
     
    unit DBGridExportToExcel;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ExtCtrls, StdCtrls, ComCtrls, DB, IniFiles, Buttons, dbgrids, ADOX_TLB, ADODB;
     
     
    type TScrollEvents = class
           BeforeScroll_Event: TDataSetNotifyEvent;
           AfterScroll_Event: TDataSetNotifyEvent;
           AutoCalcFields_Property: Boolean;
      end;
     
    procedure DisableDependencies(DataSet: TDataSet; var ScrollEvents: TScrollEvents);
    procedure EnableDependencies(DataSet: TDataSet; ScrollEvents: TScrollEvents);
    procedure DBGridToExcelADO(DBGrid: TDBGrid; FileName: string; SheetName: string);
     
     
    implementation
     
    //Support procedures: I made that in order to increase speed in
    //the process of scanning large amounts
    //of records in a dataset
     
    //we make a call to the "DisableControls" procedure and then disable the "BeforeScroll" and
    //"AfterScroll" events and the "AutoCalcFields" property.
    procedure DisableDependencies(DataSet: TDataSet; var ScrollEvents: TScrollEvents);
    begin
         with DataSet do
              begin
                   DisableControls;
                   ScrollEvents := TScrollEvents.Create();
                   with ScrollEvents do
                        begin
                             BeforeScroll_Event := BeforeScroll;
                             AfterScroll_Event := AfterScroll;
                             AutoCalcFields_Property := AutoCalcFields;
                             BeforeScroll := nil;
                             AfterScroll := nil;
                             AutoCalcFields := False;
                        end;
              end;
    end;
     
    //we make a call to the "EnableControls" procedure and then restore
    // the "BeforeScroll" and "AfterScroll" events and the "AutoCalcFields" property.
    procedure EnableDependencies(DataSet: TDataSet; ScrollEvents: TScrollEvents);
    begin
         with DataSet do
              begin
                   EnableControls;
                   with ScrollEvents do
                        begin
                             BeforeScroll := BeforeScroll_Event;
                             AfterScroll := AfterScroll_Event;
                             AutoCalcFields := AutoCalcFields_Property;
                        end;
              end;
    end;
     
    //This is the procedure which make the work:
     
    procedure DBGridToExcelADO(DBGrid: TDBGrid; FileName: string; SheetName: string);
    var
      cat: _Catalog;
      tbl: _Table;
      col: _Column;
      i: integer;
      ADOConnection: TADOConnection;
      ADOQuery: TADOQuery;
      ScrollEvents: TScrollEvents;
      SavePlace: TBookmark;
    begin
      //
      //WorkBook creation (database)
      cat := CoCatalog.Create;
      cat._Set_ActiveConnection('Provider=Microsoft.Jet.OLEDB.4.0; Data Source=' + FileName + ';Extended Properties=Excel 8.0');
      //WorkSheet creation (table)
      tbl := CoTable.Create;
      tbl.Set_Name(SheetName);
      //Columns creation (fields)
      DBGrid.DataSource.DataSet.First;
      with DBGrid.Columns do
        begin
          for i := 0 to Count - 1 do
            if Items[i].Visible then
            begin
              col := nil;
              col := CoColumn.Create;
              with col do
                begin
                  Set_Name(Items[i].Title.Caption);
                  Set_Type_(adVarWChar);
                end;
              //add column to table
              tbl.Columns.Append(col, adVarWChar, 20);
            end;
        end;
      //add table to database
      cat.Tables.Append(tbl);
     
      col := nil;
      tbl := nil;
      cat := nil;
     
      //exporting
      ADOConnection := TADOConnection.Create(nil);
      ADOConnection.LoginPrompt := False;
      ADOConnection.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0; Data Source=' + FileName + ';Extended Properties=Excel 8.0';
      ADOQuery := TADOQuery.Create(nil);
      ADOQuery.Connection := ADOConnection;
      ADOQuery.SQL.Text := 'Select * from [' + SheetName + '$]';
      ADOQuery.Open;
     
     
      DisableDependencies(DBGrid.DataSource.DataSet, ScrollEvents);
      SavePlace := DBGrid.DataSource.DataSet.GetBookmark;
      try
      with DBGrid.DataSource.DataSet do
        begin
          First;
          while not Eof do
            begin
              ADOQuery.Append;
              with DBGrid.Columns do
                begin
                  ADOQuery.Edit;
                  for i := 0 to Count - 1 do
                    if Items[i].Visible then
                      begin
                        ADOQuery.FieldByName(Items[i].Title.Caption).AsString := FieldByName(Items[i].FieldName).AsString;
                      end;
                  ADOQuery.Post;
                end;
              Next;
            end;
        end;
     
      finally
      DBGrid.DataSource.DataSet.GotoBookmark(SavePlace);
      DBGrid.DataSource.DataSet.FreeBookmark(SavePlace);
      EnableDependencies(DBGrid.DataSource.DataSet, ScrollEvents);
     
      ADOQuery.Close;
      ADOConnection.Close;
     
      ADOQuery.Free;
      ADOConnection.Free;
     
      end;
     
    end;
     
    end.
    J-L aka Papy pour les amis

  11. #11
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 568
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par yandi Voir le message
    Je suis débutante dans ce domaine un lien pour m'expliquer tout et en détail
    On n'a même pas eu les réponses aux questions posées ! Comment dans ces conditions, proposé une démarche.
    Quant aux liens, je pensais qu'il y en avait déjà pas mal, ShaileTroll en avait déjà fourni pas mal.

    Et la , premier réflexe à avoir, est bien fournie https://delphi.developpez.com/faq/?page=Microsoft-Excel
    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

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/01/2021, 15h10
  2. Réponses: 1
    Dernier message: 02/10/2019, 19h40
  3. exploiter une base de données excel avec delphi
    Par budylove dans le forum Bases de données
    Réponses: 2
    Dernier message: 01/02/2005, 19h37
  4. Récupérer la couleur d'une cellule excel par Delphi
    Par teamsebracing dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 05/06/2003, 14h50
  5. cours directx francais sur delphi
    Par charly dans le forum DirectX
    Réponses: 2
    Dernier message: 28/05/2002, 17h29

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