2013-05-20 45 views
6

我想從delphi 7中的stringgrid導出數據到microsoft excel。我一直在用這個代碼去做:導出delphi stringgrid 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; 

但是當數據很大時,需要很長時間才能完成。還有其他更快的方式將數據從delphi 7 stringgrid導出爲ex​​cel嗎?

+0

感謝您的快速反應,夥計們。我認爲數組方法最適合我的情況,因爲我不打算使用.csv文件。我如何將這個問題標記爲「已解決」? – dapidmini

回答

18

的最快方法是使用變的數組,只是通過整個數組到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

感謝您的快速響應。非常明確的步驟像我這樣的初學者。這解決了我的問題。這是一個恥辱,我不能評分答案呢.. – dapidmini

+0

+1,只是想知道最快是指代碼所需的時間,或做實際「複製」所需的時間?另一種方法是將剪貼板上的所有內容以csv格式存儲,然後將剪貼板內容粘貼到Excel中。 –

+1

@MarjanVenema:剪貼板屬於用戶,而不是程序員,所以IMO不是一個選項。直接從變體陣列到Excel範圍是非常快速的,並且不會與用戶放入剪貼板期望它在稍後出現的任何內容結合在一起。 –

3

的問題是,您所要求的每一個細胞Excel對象;這在最好的時候是一個緩慢的操作,因此爲大量細胞做這件事需要很長時間。不久之前,我遇到過這樣的情況:4000行9列需要大約44秒才能轉移到Excel。

我目前的解決方案包括創建一個CSV文件,然後導入該CSV到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; 

另一種方式來自Mike Shkolnik這我引用的是:

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; 

我建議您嘗試兩種方法,看看哪是你的目的更快。

+0

感謝您的快速響應。因爲我不認爲我會使用csv文件,所以我現在只使用陣列解決方案。不幸的是我還不能評分答案。 – dapidmini

+0

@dapidmini:csv方法的優點是可以在事先不知道行數的情況下使用。顯然這不會發生在一個stringgrid中,但是如果你想將查詢的結果傳遞給Excel,它會發生。這是一個恥辱,你標記的答案沒有參考其來源。 –

+0

@dapidmini:使用csv格式,你也可以使用剪貼板,如果需要的話,不要先寫入文件。 –