2013-05-20 16 views
6

Sto cercando di esportare i dati da un grid in delphi 7 a microsoft excel. Sto usando questo codice per farlo:export delphi stringgrid to excel

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; 

ma quando i dati è grande, ci vuole molto tempo per terminare. c'è un altro modo più veloce per esportare i dati da delphi 7 per il stringgrid per eccellere?

+0

grazie per la rapida risposta, ragazzi. Penso che il metodo array sia il migliore per la mia situazione in questo momento perché non userò il file .csv. come contrassegno questa domanda come "Risolto"? – dapidmini

risposta

18

Il modo più veloce è quello di utilizzare una vasta gamma di varianti, e basta passare l'intero 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

grazie per la rapida risposta. passi molto chiari per un principiante come me. questo ha risolto il mio problema. è un peccato non posso ancora valutare una risposta .. – dapidmini

+0

+1, mi chiedo solo se il riferimento più rapido è il tempo necessario per il codice o il tempo necessario per eseguire la "copia" effettiva? Un altro modo sarebbe, ad esempio, quello di mettere tutto negli appunti in un formato CSV e quindi incollare il contenuto degli appunti in Excel. –

+1

@ MarjanVenema: Gli appunti appartengono all'utente, non al programmatore, quindi IMO non è un'opzione. Passare direttamente dalla serie di varianti alla gamma di Excel è estremamente veloce e non rovina nulla di ciò che l'utente ha inserito negli appunti aspettandosi che ci fosse in seguito. –

3

Il problema è che si sta chiamando l'oggetto di Excel per ogni cella; questa è un'operazione lenta nel migliore dei casi, quindi fare questo per un gran numero di celle richiederà molto tempo. Ho avuto un caso di questo non molto tempo fa: 4000 righe con 9 colonne sono voluti circa 44 secondi per il trasferimento in Excel.

La mia soluzione attuale prevede la creazione di un file CSV e quindi l'importazione di 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; 

Un altro modo viene da Mike Shkolnik che sto citando come è:

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; 

io suggerisco di provare entrambi i metodi e vedere che è più veloce per i vostri scopi.

+0

grazie per la rapida risposta. dal momento che non penso che userò il file csv, per ora userò semplicemente la soluzione array. sfortunatamente non posso ancora esprimere una risposta. – dapidmini

+0

@dapidmini: il vantaggio del metodo csv è che può essere utilizzato quando il numero di righe non è noto in anticipo. Ovviamente questo non accadrà con un grid-string, ma succederà se si desidera passare i risultati di una query a Excel. E 'un peccato che tu abbia segnato la risposta che non ha fatto riferimento alla sua fonte. –

+0

@dapidmini: usando il formato csv puoi anche usare gli appunti, se lo desideri senza scriverlo prima nel file. –