2013-05-20 18 views
6

私はdelphi 7の文字列グリッドからmicrosoft excelにデータをエクスポートしようとしています。 excelにdelphiの文字列グリッドをエクスポートする

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; 
をするが、データが大きい場合、それが終了するのに非常に長い時間がかかる:私はそれを行うには、このコードを使用してきました。デルファイ7 stringgridからデータをエクスポートする他の高速な方法はありますか?

+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、最速のコードに必要な時間を参照するか、実際の "コピー"を行うために必要な時間を参照してくださいか?もう1つの方法は、たとえば、クリップボードにすべてをcsv形式で置き、クリップボードの内容をExcelに貼り付けることです。 –

+1

@MarjanVenema:クリップボードはプログラマではなくユーザに属しているので、IMOはオプションではありません。バリアントの配列からExcelの範囲にまっすぐ行くのは非常に高速で、ユーザーが後でそこに来ることを期待してクリップボードに入れたものとはまったく一致しません。 –

3

問題は、あなたがすべてのセルのためのExcelオブジェクトを呼び出しているということです。これは時間のかかる操作が遅いため、多数のセルに対してこれを実行することは長い時間がかかることになります。私はそれほど前に、Excelに転送するのに約9秒かかっていました。

私の現在の解決策は、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メソッドの利点は、行数が事前にわかっていない場合に使用できることです。明らかにこれは文字列グリッドでは起こりませんが、クエリーの結果をExcelに渡したい場合に起こります。ソースを参照していない回答をマークしたことは残念です。 –

+0

@dapidmini:csv形式を使用すると、必要に応じてクリップボードをファイルに書き込まずに使用することもできます。 –

関連する問題