2013-05-20 25 views
6

Tôi đang cố xuất dữ liệu từ chuỗi ký tự trong delphi 7 thành microsoft excel. Tôi đã sử dụng mã này để làm điều đó:xuất khẩu delphi stringgrid thành 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; 

nhưng khi dữ liệu lớn thì phải mất rất nhiều thời gian để hoàn thành. là có cách nào khác nhanh hơn để xuất dữ liệu từ delphi 7 stringgrid để excel?

+0

cảm ơn phản hồi nhanh, các bạn. Tôi nghĩ rằng phương pháp mảng là tốt nhất cho tình hình của tôi ngay bây giờ bởi vì tôi sẽ không sử dụng tệp .csv. làm cách nào để gắn cờ câu hỏi này là "Đã giải quyết"? – dapidmini

Trả lời

18

Cách nhanh nhất là sử dụng một loạt các biến thể, và chỉ cần vượt qua toàn bộ mảng sang 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

cảm ơn phản hồi nhanh. các bước rất rõ ràng cho người mới bắt đầu như tôi. điều này giải quyết được vấn đề của tôi. đó là một sự xấu hổ tôi không thể đánh giá một câu trả lời nào được nêu ra .. – dapidmini

+0

+1, chỉ cần tự hỏi liệu nhanh nhất có đề cập đến thời gian cần thiết để viết mã hay thời gian cần thiết để thực hiện "bản sao" thực tế? Ví dụ, một cách khác là đặt tất cả mọi thứ vào clipboard theo định dạng csv và sau đó dán nội dung clipboard vào Excel. –

+1

@MarjanVenema: Clipboard thuộc về người dùng chứ không phải lập trình viên, vì vậy IMO không phải là tùy chọn. Đi thẳng từ mảng biến thể sang phạm vi Excel cực kỳ nhanh, và không vặn vẹo với bất kỳ thứ gì người dùng đã đưa vào khay nhớ tạm mong đợi ở đó sau này. –

3

Vấn đề là bạn đang gọi đối tượng Excel cho mỗi tế bào; đây là một hoạt động chậm ở thời điểm tốt nhất, do đó, làm điều này cho một số lượng lớn các tế bào sẽ mất một thời gian dài. Tôi đã có một trường hợp này cách đây không lâu: 4000 hàng với 9 cột mất khoảng 44 giây để chuyển sang Excel.

Giải pháp hiện tại của tôi liên quan đến việc tạo tệp csv, sau đó nhập csv đó vào 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; 

Một cách khác xuất phát từ Mike Shkolnik mà tôi đang trích dẫn như là:

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; 

tôi đề nghị bạn nên thử cả hai phương pháp và xem đó là nhanh hơn cho mục đích của bạn.

+0

cảm ơn phản ứng nhanh. vì tôi không nghĩ rằng tôi sẽ sử dụng tệp csv, tôi sẽ chỉ sử dụng giải pháp mảng ngay bây giờ. Rất tiếc, tôi chưa thể xếp hạng câu trả lời. – dapidmini

+0

@dapidmini: Lợi thế của phương pháp csv là nó có thể được sử dụng khi số hàng không được biết trước. Rõ ràng điều này sẽ không xảy ra với một stringgrid nhưng nó sẽ xảy ra nếu bạn muốn chuyển kết quả của một truy vấn đến Excel. Đó là một sự xấu hổ mà bạn đánh dấu câu trả lời mà không tham chiếu nguồn của nó. –

+0

@dapidmini: sử dụng định dạng csv bạn cũng có thể sử dụng khay nhớ tạm, nếu muốn như vậy mà không cần ghi nó vào tệp trước. –