2013-05-20 18 views
6

Ich versuche, Daten aus einem Stringgrid in Delphi 7 zu Microsoft Excel zu exportieren. Ich habe diesen Code benutze es zu tun:Export Delphi Stringgrid zu übertreffen

objExcel := TExcelApplication.Create(nil); 
    objExcel.Visible[LOCALE_USER_DEFAULT] := true; 
    objWB := objExcel.workbooks.add(null,LOCALE_USER_DEFAULT); 
    lineNumber := 1; 

    for i:=1 to stringgrid1.rowcount-1 do begin 
    for j:=0 to stringgrid1.ColCount-1 do begin 
     objWB.Worksheets.Application.Cells.Item[i+lineNumber,j+1] := ''''+stringgrid1.Cells[j,i]; 
    end; 
    end; 

aber, wenn die Daten groß ist, dauert es eine sehr lange Zeit zu beenden. Gibt es andere schnellere Möglichkeit, Daten aus Delphi 7 Stringgrid zu Excel zu exportieren?

+0

danke für die schnelle Antwort, Leute. Ich denke, dass die Array-Methode jetzt am besten für meine Situation ist, weil ich die .csv-Datei nicht verwenden werde. Wie markiere ich diese Frage als "Gelöst"? – dapidmini

Antwort

18

Der schnellste Weg ist ein Array von Variant zu verwenden, und übergeben Sie einfach das gesamte Array in Excel:

var 
    xls, wb, Range: OLEVariant; 
    arrData: Variant; 
    RowCount, ColCount, i, j: Integer; 
begin 
    {create variant array where we'll copy our data} 
    RowCount := StringGrid1.RowCount; 
    ColCount := StringGrid1.ColCount 
    arrData := VarArrayCreate([1, RowCount, 1, ColCount], varVariant); 

    {fill array} 
    for i := 1 to RowCount do 
    for j := 1 to ColCount do 
     arrData[i, j] := StringGrid1.Cells[j-1, i-1]; 

    {initialize an instance of Excel} 
    xls := CreateOLEObject('Excel.Application'); 

    {create workbook} 
    wb := xls.Workbooks.Add; 

    {retrieve a range where data must be placed} 
    Range := wb.WorkSheets[1].Range[wb.WorkSheets[1].Cells[1, 1], 
            wb.WorkSheets[1].Cells[RowCount, ColCount]]; 

    {copy data from allocated variant array} 
    Range.Value := arrData; 

    {show Excel with our data} 
    xls.Visible := True; 
end; 
+0

danke für die schnelle Antwort. sehr klare Schritte für einen Anfänger wie mich. Das hat mein Problem gelöst. Es ist eine Schande, dass ich eine Antwort noch nicht bewerten kann. – dapidmini

+0

+1, frage mich nur, ob sich am schnellsten auf die benötigte Zeit für den Code oder die benötigte Zeit bezieht, um die eigentliche "Kopie" zu machen? Ein anderer Weg wäre zum Beispiel, alles in die Zwischenablage im CSV-Format zu legen und dann den Inhalt der Zwischenablage in Excel einzufügen. –

+1

@MarjanVenema: Die Zwischenablage gehört dem Benutzer, nicht dem Programmierer, also IMO ist es keine Option. Direkt vom Array-Bereich zum Excel-Bereich zu gelangen, ist extrem schnell und bringt nichts mit, was der Benutzer in die Zwischenablage geschrieben hat und erwartet, dass er später da ist. –

3

Das Problem ist, dass Sie das Excel-Objekt für jede Zelle rufen; Dies ist eine langsame Operation zu den besten Zeiten, so wird dies für eine große Anzahl von Zellen lange dauern. Ich hatte einen Fall von diesem nicht so lange her: 4000 Zeilen mit 9 Spalten dauerte etwa 44 Sekunden, um nach Excel zu übertragen.

Meine aktuelle Lösung umfasst das Erstellen einer CSV-Datei dann das Importieren dieser CSV in Excel.

const 
fn = 'c:\windows\temp\csv.csv'; 

var 
csv: tstringlist; 
row, col: integer; 
s: string; 

begin 
csv:= tstringlist.create; 
for row:= 1 to stringgrid1.rowcount do 
    begin 
    s:= ''; 
    for col:= 0 to stringgrid1.ColCount-1 do 
    s:= s + stringgrid1.Cells[col, row-1] + ','; 
    csv.add (s) 
    end; 

csv.savetofile (fn); 
csv.free; 

objExcel := TExcelApplication.Create(nil); 
objExcel.workbooks.open (fn); 
deletefile (fn); 
end; 

Ein anderer Weg, kommt aus Mike Shkolnik was ich zitiere bin wie:

var 
xls, wb, Range: OLEVariant; 
arrData: Variant; 

begin 
{create variant array where we'll copy our data} 
arrData := VarArrayCreate([1, yourStringGrid.RowCount, 1, yourStringGrid.ColCount], varVariant); 

{fill array} 
for i := 1 to yourStringGrid.RowCount do 
    for j := 1 to yourStringGrid.ColCount do 
    arrData[i, j] := yourStringGrid.Cells[j-1, i-1]; 

{initialize an instance of Excel} 
xls := CreateOLEObject('Excel.Application'); 

{create workbook} 
wb := xls.Workbooks.Add; 

{retrieve a range where data must be placed} 
Range := wb.WorkSheets[1].Range[wb.WorkSheets[1].Cells[1, 1], 
           wb.WorkSheets[1].Cells[yourStringGrid.RowCount, yourStringGrid.ColCount]]; 

{copy data from allocated variant array} 
Range.Value := arrData; 

{show Excel with our data} 
xls.Visible := True; 
end; 

Ich schlage vor, dass Sie beide Methoden versuchen und sehen, welche schneller für Ihre Zwecke ist.

+0

danke für die schnelle Antwort. Da ich glaube nicht, dass ich die CSV-Datei verwenden werde, werde ich nur die Array-Lösung für jetzt verwenden. Leider kann ich eine Antwort noch nicht bewerten. – dapidmini

+0

@dapidmini: Der Vorteil der csv-Methode besteht darin, dass sie verwendet werden kann, wenn die Anzahl der Zeilen nicht im Voraus bekannt ist. Offensichtlich wird dies nicht mit einem Stringgrid passieren, aber es wird passieren, wenn Sie die Ergebnisse einer Abfrage an Excel übergeben möchten. Es ist eine Schande, dass Sie die Antwort markiert haben, die seine Quelle nicht erwähnt hat. –

+0

@dapidmini: Mit dem CSV-Format können Sie auch die Zwischenablage verwenden, wenn Sie möchten, ohne sie zuerst in die Datei zu schreiben. –