2013-05-20 42 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格式,你也可以使用剪贴板,如果需要的话,不要先写入文件。 –