bestlong 怕失憶論壇

 

 

搜索
bestlong 怕失憶論壇 論壇 Delphi 用 OLE 把 DBGrid 内容输出到Excel
查看: 9642|回復: 3
go

用 OLE 把 DBGrid 内容输出到Excel [複製鏈接]

Rank: 9Rank: 9Rank: 9

1#
發表於 2010-1-24 14:36 |只看該作者 |倒序瀏覽 |打印
需要引用单元 ComObj, Excel2000,下面过程是将 DBGrid 中的数据拷贝到 Excel 中。
  1. procedure CopyDbDataToExcel(Target: TDbgrid);
  2. var
  3.   iCount, jCount: Integer;
  4.   XLApp: Variant;
  5.   Sheet: Variant;
  6. begin
  7.   Screen.Cursor := crHourGlass;
  8.   if not VarIsEmpty(XLApp) then
  9.   begin
  10.     XLApp.DisplayAlerts := False;
  11.     XLApp.Quit;
  12.     VarClear(XLApp);
  13.   end;
  14.   //通过 ole 创建 Excel 对象
  15.   try
  16.     XLApp := CreateOleObject('Excel.Application');
  17.   except
  18.     Screen.Cursor := crDefault;
  19.     Exit;
  20.   end;
  21.   XLApp.WorkBooks.Add[XLWBatWorksheet];
  22.   XLApp.WorkBooks[1].WorkSheets[1].Name := '测试工作薄';
  23.   Sheet := XLApp.Workbooks[1].WorkSheets['测试工作薄'];
  24.   if not Target.DataSource.DataSet.Active then
  25.   begin
  26.     Screen.Cursor := crDefault;
  27.     Exit;
  28.   end;
  29.   Target.DataSource.DataSet.first;

  30.   for iCount := 0 to Target.Columns.Count - 1 do
  31.   begin
  32.     Sheet.cells[1, iCount + 1] := Target.Columns.Items[iCount].Title.Caption;
  33.   end;
  34.   jCount := 1;
  35.   while not Target.DataSource.DataSet.Eof do
  36.   begin
  37.     for iCount := 0 to Target.Columns.Count - 1 do
  38.     begin
  39.       Sheet.cells[jCount + 1, iCount + 1] := Target.Columns.Items[iCount].Field.AsString;
  40.     end;
  41.     Inc(jCount);
  42.     Target.DataSource.DataSet.Next;
  43.   end;
  44.   XlApp.Visible := True;
  45.   Screen.Cursor := crDefault;
  46. end;
複製代碼
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

2#
發表於 2011-4-7 16:44 |只看該作者
使用者反應匯出 Excel 存檔後再開啟的操作流程太繁瑣, 所以將 DBGrid 的內容直接傳到 Excel 開啟來檢視.

文字欄位特別加強處理將儲存格設定成文字格式,
避免純數字的文字資料被當成數字處理, 所以有 0 開頭(零開頭)的資料就不會被刪掉了.

dbgrid2excel.jpg

在上面圖片中的某些儲存格左上有綠色小三角就是處理的重點.
  1. procedure DBGridToExcel(ADBGrid: TDBGrid);
  2. const
  3.   xlWBatWorkSheet = -4167;
  4. var
  5.   iCol, iRow: Integer;
  6.   sCell: string;
  7.   ExcelApp, Sheet: OleVariant;

  8.   function GetColA2Z(Col: Integer):string; //欄位超過 Z 怎麼辦? 這裡幫你算啦~
  9.   begin
  10.     if (Col mod 26 = 0) then
  11.       Result := 'Z'
  12.     else
  13.       Result := Chr((Col mod 26)+64);
  14.     //遞迴, 就算你 ZZZ 我也幫你算
  15.     if Col > 26 then
  16.       Result := GetColA2Z(Col div 26) + Result;
  17.   end;

  18. begin
  19.   try
  20.     try
  21.       ExcelApp := CreateOleObject('Excel.Application');
  22.       ExcelApp.Visible := False;
  23.     except
  24.       ShowMessage('連結 Excel 錯誤');
  25.       Exit;
  26.     end;
  27.     ExcelApp.WorkBooks.Add(xlWBatWorkSheet);
  28.     Sheet := ExcelApp.WorkBooks[1].WorkSheets[1];
  29.     //輸出標題
  30.     iRow := 1;
  31.     for iCol := 0 to ADBGrid.FieldCount - 1 do
  32.     begin
  33.         sCell := GetColA2Z(iCol+1) + IntToStr(iRow);
  34.         Sheet.Cells.Range[sCell, sCell].NumberFormatLocal := '@'; //標題都設為文字格式
  35.         Sheet.Cells.Range[sCell, sCell].Value := ADBGrid.Columns.Items[iCol].Title.Caption;
  36. //        Sheet.Cells[1, iCol + 1].Value := ADBGrid.Columns.Items[iCol].Title.Caption;
  37.     end;
  38.     //輸出資料
  39.     iRow := 2;
  40.     ADBGrid.DataSource.DataSet.DisableControls;
  41.     ADBGrid.DataSource.DataSet.First;
  42.     while not ADBGrid.DataSource.DataSet.Eof do
  43.     begin
  44.       for iCol := 0 to ADBGrid.FieldCount -1 do
  45.       begin
  46.         sCell := GetColA2Z(iCol+1) + IntToStr(iRow);
  47.         if ADBGrid.Fields[iCol].DataType in [ftString, ftMemo, ftWideString] then
  48.         begin
  49.           Sheet.Cells.Range[sCell, sCell].NumberFormatLocal := '@';
  50.         end;
  51.         Sheet.Cells.Range[sCell, sCell].Value := ADBGrid.Fields[iCol].AsString;
  52. //        Sheet.Cells[iRow, iCol + 1].Value := ADBGrid.Fields[iCol].AsString;
  53.       end;
  54.       ADBGrid.DataSource.DataSet.Next;
  55.       Inc(iRow);
  56.     end;
  57.     ExcelApp.Visible := True;
  58.   finally
  59.     ADBGrid.DataSource.DataSet.EnableControls;
  60.     if not VarIsEmpty(ExcelApp) then
  61.     begin
  62.       Sheet := Unassigned;
  63.       ExcelApp := Unassigned;
  64.     end;
  65.   end;
  66. end;
複製代碼
不過執行的速度有些慢, 需要再加強.
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

3#
發表於 2011-4-7 16:54 |只看該作者
從 DBGrid/StringGrid 匯出資料到 Excel 的元件 (Demo+Source)
http://delphi.ktop.com.tw/board. ... id=79&tid=62999
作者 silence
// 因為工作上使用到的, 幫部門寫的小程式經常要輸出 Excel
// 所以寫個元件來簡化
//
// 功能:
// 1. DBGrid 或 StringGrid 上按下右鍵後可以選擇 [輸出到 Excel]
// 2. 自動生成 PopupMenu / MenuItem, 並整合入自訂的 PopupMenu, 不必額外煩惱操作介面
// 3. DBGrid 可使用按下 Title 後做 Sort 的功能 (但 DBGrid 的 DataSet 要是 SQL Query, 且不能太複雜)
// 4. 在執行時期若要關閉, 不允許 user 轉出資料, 只要將特定 Grid 的 forbidden := nil 即可
//    要再打開, 只要重新 Initial 即可
//
// 使用:
// 0. 將元件拉放到 Form 上
// 1. 在 FormCreate 中加入
//    GridExport.Initial(Self);
//    即可自動使用, 額外有預設為 False 的參數 aTitleSort: boolean
// 2. 在 FormClose 中加入
//    GridExport.FreeAll;
//    確保 [自有物件] 及 Excel 正確 Free
// 3. 程式執行時, 於 DBGrid / StringGrid 上按右鍵跳出 PopupMenu,
//    其中 MenuItem 會自動跟你指定給 Grid 的 PopupMenu 結合
// 4. 執行 Export to Excel, 從 DBGrid / StringGrid 將資料匯出到 Excel
//
// 附帶函式四個
// A. 自動設定 String Grid 的第 aCol 個 column width
// B. 應用 A 來做多個 column 的自動調整
// C. "自訂 DBGrid 的文字外觀時, 放在 OnDrawColumnCell 的最後來使用"
// D. "自訂 StringGrid 的文字外觀時, 放在 OnDrawCell 的最後來使用"

總是看網站上很多人問 DB to Excel 的問題
所以也上來現個醜
其實我只用很簡單的想法和oo觀念而已
原先在另一 Delphi 討論站有發表過舊的版本(太久沒去都忘了站名)
而來到 KTop 又發現一些新東西就再加進去
(例如 DBGrid 文字外觀的 Alignment)
使用很久了, 從 D6 ~ D7 都沒問題
又很簡單
只要丟著再加兩行程式就好了
有興趣看看 Suorce 吧
有覺得不夠精簡的地方非常歡迎來信
想自行擴充也沒關係, 沒有任何限制
只希望改完也來把好主意與大家分享

另: 公司網路慢, 沒有仔細爬, 若站上已有類似的元件請勿見怪


62999_GridExport.rar (374.28 KB, 下載次數: 370)
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw

Rank: 9Rank: 9Rank: 9

4#
發表於 2011-4-7 17:24 |只看該作者
export a StringGrid to an Excel-File?
  1. {1. With OLE Automation }

  2. uses
  3.   ComObj;

  4. function RefToCell(ARow, ACol: Integer): string;
  5. begin
  6.   Result := Chr(Ord('A') + ACol - 1) + IntToStr(ARow);
  7. end;

  8. function SaveAsExcelFile(AGrid: TStringGrid; ASheetName, AFileName: string): Boolean;
  9. const
  10.   xlWBATWorksheet = -4167;
  11. var
  12.   Row, Col: Integer;
  13.   GridPrevFile: string;
  14.   XLApp, Sheet, Data: OLEVariant;
  15.   i, j: Integer;
  16. begin
  17.   // Prepare Data
  18.   Data := VarArrayCreate([1, AGrid.RowCount, 1, AGrid.ColCount], varVariant);
  19.   for i := 0 to AGrid.ColCount - 1 do
  20.     for j := 0 to AGrid.RowCount - 1 do
  21.       Data[j + 1, i + 1] := AGrid.Cells[i, j];
  22.   // Create Excel-OLE Object
  23.   Result := False;
  24.   XLApp := CreateOleObject('Excel.Application');
  25.   try
  26.     // Hide Excel
  27.     XLApp.Visible := False;
  28.     // Add new Workbook
  29.     XLApp.Workbooks.Add(xlWBatWorkSheet);
  30.     Sheet := XLApp.Workbooks[1].WorkSheets[1];
  31.     Sheet.Name := ASheetName;
  32.     // Fill up the sheet
  33.     Sheet.Range[RefToCell(1, 1), RefToCell(AGrid.RowCount,
  34.       AGrid.ColCount)].Value := Data;
  35.     // Save Excel Worksheet
  36.     try
  37.       XLApp.Workbooks[1].SaveAs(AFileName);
  38.       Result := True;
  39.     except
  40.       // Error ?
  41.     end;
  42.   finally
  43.     // Quit Excel
  44.     if not VarIsEmpty(XLApp) then
  45.     begin
  46.       XLApp.DisplayAlerts := False;
  47.       XLApp.Quit;
  48.       XLAPP := Unassigned;
  49.       Sheet := Unassigned;
  50.     end;
  51.   end;
  52. end;

  53. // Example:

  54. procedure TForm1.Button1Click(Sender: TObject);
  55. begin
  56.   if SaveAsExcelFile(stringGrid1, 'My Stringgrid Data', 'c:\MyExcelFile.xls') then
  57.     ShowMessage('StringGrid saved!');
  58. end;


  59. {**************************************************************}
  60. {2. Without OLE }

  61. procedure XlsWriteCellLabel(XlsStream: TStream; const ACol, ARow: Word;
  62.   const AValue: string);
  63. var
  64.   L: Word;
  65. const
  66.   {$J+}
  67.   CXlsLabel: array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
  68.   {$J-}
  69. begin
  70.   L := Length(AValue);
  71.   CXlsLabel[1] := 8 + L;
  72.   CXlsLabel[2] := ARow;
  73.   CXlsLabel[3] := ACol;
  74.   CXlsLabel[5] := L;
  75.   XlsStream.WriteBuffer(CXlsLabel, SizeOf(CXlsLabel));
  76.   XlsStream.WriteBuffer(Pointer(AValue)^, L);
  77. end;


  78. function SaveAsExcelFile(AGrid: TStringGrid; AFileName: string): Boolean;
  79. const
  80.   {$J+} CXlsBof: array[0..5] of Word = ($809, 8, 00, $10, 0, 0); {$J-}
  81.   CXlsEof: array[0..1] of Word = ($0A, 00);
  82. var
  83.   FStream: TFileStream;
  84.   I, J: Integer;
  85. begin
  86.   Result := False;
  87.   FStream := TFileStream.Create(PChar(AFileName), fmCreate or fmOpenWrite);
  88.   try
  89.     CXlsBof[4] := 0;
  90.     FStream.WriteBuffer(CXlsBof, SizeOf(CXlsBof));
  91.     for i := 0 to AGrid.ColCount - 1 do
  92.       for j := 0 to AGrid.RowCount - 1 do
  93.         XlsWriteCellLabel(FStream, I, J, AGrid.cells[i, j]);
  94.     FStream.WriteBuffer(CXlsEof, SizeOf(CXlsEof));
  95.     Result := True;
  96.   finally
  97.     FStream.Free;
  98.   end;
  99. end;

  100. // Example:

  101. procedure TForm1.Button2Click(Sender: TObject);
  102. begin
  103.   if SaveAsExcelFile(StringGrid1, 'c:\MyExcelFile.xls') then
  104.     ShowMessage('StringGrid saved!');
  105. end;

  106. {**************************************************************}
  107. {3. Code by Reinhard Schatzl }

  108. uses
  109.   ComObj;

  110. // Hilfsfunktion für StringGridToExcelSheet
  111. // Helper function for StringGridToExcelSheet
  112. function RefToCell(RowID, ColID: Integer): string;
  113. var
  114.   ACount, APos: Integer;
  115. begin
  116.   ACount := ColID div 26;
  117.   APos := ColID mod 26;
  118.   if APos = 0 then
  119.   begin
  120.     ACount := ACount - 1;
  121.     APos := 26;
  122.   end;

  123.   if ACount = 0 then
  124.     Result := Chr(Ord('A') + ColID - 1) + IntToStr(RowID);

  125.   if ACount = 1 then
  126.     Result := 'A' + Chr(Ord('A') + APos - 1) + IntToStr(RowID);

  127.   if ACount > 1 then
  128.     Result := Chr(Ord('A') + ACount - 1) + Chr(Ord('A') + APos - 1) + IntToStr(RowID);
  129. end;

  130. // StringGrid Inhalt in Excel exportieren
  131. // Export StringGrid contents to Excel
  132. function StringGridToExcelSheet(Grid: TStringGrid; SheetName, FileName: string;
  133.   ShowExcel: Boolean): Boolean;
  134. const
  135.   xlWBATWorksheet = -4167;
  136. var
  137.   SheetCount, SheetColCount, SheetRowCount, BookCount: Integer;
  138.   XLApp, Sheet, Data: OLEVariant;
  139.   I, J, N, M: Integer;
  140.   SaveFileName: string;
  141. begin
  142.   //notwendige Sheetanzahl feststellen
  143.   SheetCount := (Grid.ColCount div 256) + 1;
  144.   if Grid.ColCount mod 256 = 0 then
  145.     SheetCount := SheetCount - 1;
  146.   //notwendige Bookanzahl feststellen
  147.   BookCount := (Grid.RowCount div 65536) + 1;
  148.   if Grid.RowCount mod 65536 = 0 then
  149.     BookCount := BookCount - 1;

  150.   //Create Excel-OLE Object
  151.   Result := False;
  152.   XLApp  := CreateOleObject('Excel.Application');
  153.   try
  154.     //Excelsheet anzeigen
  155.     if ShowExcel = False then
  156.       XLApp.Visible := False
  157.     else
  158.       XLApp.Visible := True;
  159.     //Workbook hinzufügen
  160.     for M := 1 to BookCount do
  161.     begin
  162.       XLApp.Workbooks.Add(xlWBATWorksheet);
  163.       //Sheets anlegen
  164.       for N := 1 to SheetCount - 1 do
  165.       begin
  166.         XLApp.Worksheets.Add;
  167.       end;
  168.     end;
  169.     //Sheet ColAnzahl feststellen
  170.     if Grid.ColCount <= 256 then
  171.       SheetColCount := Grid.ColCount
  172.     else
  173.       SheetColCount := 256;
  174.     //Sheet RowAnzahl feststellen
  175.     if Grid.RowCount <= 65536 then
  176.       SheetRowCount := Grid.RowCount
  177.     else
  178.       SheetRowCount := 65536;

  179.     //Sheets befüllen
  180.     for M := 1 to BookCount do
  181.     begin
  182.       for N := 1 to SheetCount do
  183.       begin
  184.         //Daten aus Grid holen
  185.         Data := VarArrayCreate([1, Grid.RowCount, 1, SheetColCount], varVariant);
  186.         for I := 0 to SheetColCount - 1 do
  187.           for J := 0 to SheetRowCount - 1 do
  188.             if ((I + 256 * (N - 1)) <= Grid.ColCount) and
  189.               ((J + 65536 * (M - 1)) <= Grid.RowCount) then
  190.               Data[J + 1, I + 1] := Grid.Cells[I + 256 * (N - 1), J + 65536 * (M - 1)];
  191.         //-------------------------
  192.         XLApp.Worksheets[N].Select;
  193.         XLApp.Workbooks[M].Worksheets[N].Name := SheetName + IntToStr(N);
  194.         //Zellen als String Formatieren
  195.         XLApp.Workbooks[M].Worksheets[N].Range[RefToCell(1, 1),
  196.           RefToCell(SheetRowCount, SheetColCount)].Select;
  197.         XLApp.Selection.NumberFormat := '@';
  198.         XLApp.Workbooks[M].Worksheets[N].Range['A1'].Select;
  199.         //Daten dem Excelsheet übergeben
  200.         Sheet := XLApp.Workbooks[M].WorkSheets[N];
  201.         Sheet.Range[RefToCell(1, 1), RefToCell(SheetRowCount, SheetColCount)].Value :=
  202.           Data;
  203.       end;
  204.     end;
  205.     //Save Excel Worksheet
  206.     try
  207.       for M := 1 to BookCount do
  208.       begin
  209.         SaveFileName := Copy(FileName, 1,Pos('.', FileName) - 1) + IntToStr(M) +
  210.           Copy(FileName, Pos('.', FileName),
  211.           Length(FileName) - Pos('.', FileName) + 1);
  212.         XLApp.Workbooks[M].SaveAs(SaveFileName);
  213.       end;
  214.       Result := True;
  215.     except
  216.       // Error ?
  217.     end;
  218.   finally
  219.     //Excel Beenden
  220.     if (not VarIsEmpty(XLApp)) and (ShowExcel = False) then
  221.     begin
  222.       XLApp.DisplayAlerts := False;
  223.       XLApp.Quit;
  224.       XLAPP := Unassigned;
  225.       Sheet := Unassigned;
  226.     end;
  227.   end;
  228. end;

  229. //Example
  230. procedure TForm1.Button1Click(Sender: TObject);
  231. begin
  232.   //StringGrid inhalt in Excel exportieren
  233.   //Grid : stringGrid, SheetName : stringgrid Print, Pfad : c:\Test\ExcelFile.xls, Excelsheet anzeigen
  234.   StringGridToExcelSheet(StringGrid, 'Stringgrid Print', 'c:\Test\ExcelFile.xls', True);
  235. end;
複製代碼
資料來源 http://www.swissdelphicenter.ch/torry/showcode.php?id=379
我是雪龍
http://blog.bestlong.idv.tw
http://www.bestlong.idv.tw
‹ 上一主題|下一主題

Archiver|怕失憶論壇

GMT+8, 2024-5-17 11:26 , Processed in 0.013156 second(s), 12 queries .

Powered by Discuz! X1.5

© 2001-2010 Comsenz Inc.