Bonjour,
Voici mon souci, je travaille une grosse source de données que je souhaite insérer dans Excel. Au départ je générais un fichier à plat sur le disque et je l'intégrais à Excel avec une commande COM. Ma source de données peut atteindre 100 000 - 150 000 lignes.
Pour optimiser les temps de traitement je créé les lignes dans une TStringList et tous les X lignes je prends le contenu je le mets dans le Clipboard. Puis je colle dans Excel.
Le fonctionnement est très aléatoire, car d'un poste à l'autre, une exception peut être relevée pour mémoire insuffisante. Par contre soit l'autre de la mise dans le Clipboard, soit au moment du past dans Excel.
Voici un extrait du code
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 function AjouteData(sReq, sNomOnglet : String ; ListeOptions : TStringList) : boolean; var iCpt : Integer; sChaineEntete : string; RensParam : TYRensParamFusion; iLigne : Integer; ListeData : TStringList; iLigneExcel : Integer; begin try Screen.Cursor := CrHourGlass; ListeData := TStringList.Create; fdmTCD.SqlTabXl.SQL.Clear; fdmTCD.SqlTabXl.Open; fdmTCD.SqlTabXl.First; result := not fdmTCD.SqlTabXl.Eof; iLigne := 0; iLigneExcel := 1; sChaineEntete := ''; // recherche des noms de colonne for iCpt := 0 to fdmTCD.SqlTabXl.FieldCount - 1 do // Ecriture des noms de colonne sChaineEntete := sChaineEntete + UpperCase(fdmTCD.SqlTabXl.Fields[iCpt].FieldName) + ';'; ListeData.Add(sChaineEntete); Inc(iLigne); // Ecriture des données while not fdmTCD.SqlTabXl.Eof do begin inc(iLigne); ListeData.Append(GetUneLigneDeDonnee); //Toutes les 100 000 lignes on va écrire dans le fichier afin de soulager la mémoire. if (iLigne mod 50000) = 0 then begin Clipboard.AsText := ListeData.Text; fdmTCD.EwsModeleTabXl.Range['A' + IntToStr(iLigneExcel), 'A' + IntToStr(iLigneExcel)].Select; fdmTCD.EwsModeleTabXl.Paste; ListeData.Clear; iLigneExcel := iLigneExcel + iLigne; iLigne := 0; end; fdmTCD.SqlTabXl.Next; end; fdmTCD.SqlTabXl.Close; //Si on a dépassé notre seuil on a stocké les données // dans un fichier. On met les dernieres lignes dedans. if ListeData.Count > 0 then begin Clipboard.AsText := ListeData.Text; fdmTCD.EwsModeleTabXl.Range['A' + IntToStr(iLigneExcel), 'A' + IntToStr(iLigneExcel)].Select; fdmTCD.EwsModeleTabXl.Paste; ListeData.Clear; end; finally fdmTCD.SqlTabXl.Close; Screen.Cursor := crDefault; DetruitObjet(RensParam); DetruitObjet(ListeData); end; end;
J'ai tenté un essai avec le code suivant, qui marche bien sur un petit ensemble de données, mais pas sur de gros :
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 procedure TForm5.Button1Click(Sender: TObject); var mem: Cardinal; ptr: Pointer; s: string; zero: Word; begin try Clipboard.Open; Clipboard.Clear; s := Liste.Text; Liste.Clear; mem := GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE, Length(s)+2); if mem=0 then raise Exception.Create('Mem'); ptr := GlobalLock(mem); Move(PChar(s)^,ptr^, Length(s)); zero := 0; Move(zero,(PChar(ptr)+Length(s))^, 2); GlobalUnlock(mem); Clipboard.SetAsHandle(CF_UNICODETEXT ,mem); finally Clipboard.Close; end; end;
Partager