文章出自:http://blog.csdn.net/suiyunonghen/archive/2009/05/21/4207564.aspx
(*
原作者: iamdream(delphi盒子)
修改: 不得闲
功能: 将DbGrid数据保存到Excel
参数:
Grid指定表格
FileName指定要保存的文件名
MaxPageRowCount指定一页最多的支持行数
ShowProgress 指定是否显示进度条
用法:
SaveDbGridAsExcel(DBGrid1,'C:\2.xls','表测试',2000);
*)
procedure SaveDbGridAsExcel(Grid: TDBGrid;const FileName,title: string;
const MaxPageRowCount: Integer = 65535;const ShowProgress: Boolean = True);
const
MAX_VAR_ONCE = 1000; //一次导出的条数
var //返回导出记录条数
Excel, varCells: Variant;
MySheet, MyCells, Cell1, Cell2, Range: OleVariant;
iRow, iCol, iSheetIdx, iVarCount, iCurRow: integer;
CurPos: TBookmark;
ProgressForm: TForm;
Prompt: TLabel;
progressBar: TProgressBar;
Panel : TPanel;
Button : TButton;
procedure ReSetObjEvent(OldEventAddr: pointer;NewEventValue: pointer;ReSetObject: TObject);
begin
TMethod(OldEventAddr^).Code := NewEventValue;
TMethod(OldEventAddr^).Data := ReSetObject;
end;
procedure ButtonClick(BtnObject: TObject;Sender: TObject);
begin
TComponent(BtnObject).Tag := Integer(MessageBox(Application.Handle,
'真的要终止数据的导出吗?','确认',
MB_OKCANCEL + MB_ICONINFORMATION) = IDOK);
end;
procedure CreateProgressForm;
begin
ProgressForm := TForm.Create(nil);
With ProgressForm do
begin
Font.Name := '宋体';
Font.Size := 10;
BorderStyle := bsNone;
Width := 280;
Height := 120;
BorderWidth := 1;
Color := clBackground;
Position := poOwnerFormCenter;
end;
Panel := TPanel.Create(ProgressForm);
with Panel do { Create Panel }
begin
Parent := ProgressForm;
Align := alClient;
BevelInner := bvNone;
BevelOuter := bvNone;
Caption := '';
end;
Prompt := TLabel.Create(Panel);
with Prompt do { Create Label }
begin
Parent := Panel;
Left := 20;
Top := 25;
Caption := '正在启动Excel,请稍候……';
end;
progressBar := TProgressBar.Create(panel);
with ProgressBar do { Create ProgressBar }
begin
Step := 1;
Parent := Panel;
Smooth := true;
Left := 20;
Top := 50;
Height := 18;
Width := 260;
end;
Button := TButton.Create(Panel);
with Button do { Create Cancel Button }
begin
Parent := Panel;
Left := 115;
Top := 80;
Caption := '关闭';
end;
ReSetObjEvent(@@Button.OnClick,@ButtonClick,Button);
ProgressForm.FormStyle := fsStayOnTop;
ProgressForm.Show;
ProgressForm.Update;
end;
begin
if (Grid.DataSource <> nil) and
(Grid.DataSource.DataSet <> nil) and
Grid.DataSource.DataSet.Active then
begin
Grid.DataSource.DataSet.DisableControls;
CurPos := Grid.DataSource.DataSet.GetBookmark;
Grid.DataSource.DataSet.First;
try
if ShowProgress then
begin
CreateProgressForm;
Button.Tag := 0;
end;
Excel := CreateOleObject('Excel.Application');
Excel.WorkBooks.Add;
Excel.Visible := False;
except
Application.Messagebox('Excel 没有安装!','操作提示', MB_IConERROR + mb_Ok);
Screen.Cursor := crDefault;
Grid.DataSource.DataSet.GotoBookmark(CurPos);
Grid.DataSource.DataSet.FreeBookmark(CurPos);
Grid.DataSource.DataSet.EnableControls;
if ProgressForm <> nil then
ProgressForm.Free;
exit;
end;
if Grid.DataSource.DataSet.RecordCount <= MAX_VAR_ONCE then
iVarCount := Grid.DataSource.DataSet.RecordCount
else iVarCount := MAX_VAR_ONCE;
varCells := VarArrayCreate([1, iVarCount,1,Grid.FieldCount],varVariant);
iSheetIdx := 1;
iRow := 0;
if ShowProgress then
begin
ProgressBar.Position := 0;
Prompt.Caption := '请等待,正在导出数据……';
ProgressBar.Max := Grid.DataSource.DataSet.RecordCount;
end;
while (not Grid.DataSource.DataSet.Eof and not ShowProgress) or
(not Grid.DataSource.DataSet.Eof and ShowProgress and (Button.Tag = 0)) do
begin
if (iRow = 0) or (iRow > MaxPageRowCount + 1) then
begin
if iSheetIdx <= Excel.WorkBooks[1].WorkSheets.Count then
MySheet := Excel.WorkBooks[1].WorkSheets[iSheetIdx]
else
MySheet := Excel.WorkBooks[1].WorkSheets.Add(NULL, MySheet);//加在后面
MySheet.Name := Title + IntToStr(iSheetIdx);
MyCells := MySheet.Cells;
Inc(iSheetIdx);
//开始新的数据表
iRow := 1;
//写入表头
for iCol := 1 to Grid.FieldCount do
begin
MySheet.Cells[1, iCol] := Grid.Columns[iCol-1].Title.Caption;
MySheet.Cells[1, iCol].Font.Bold := True;
if (Grid.Fields[iCol - 1].DataType = ftString) or
(Grid.Fields[iCol - 1].DataType = ftWideString) then
//对于“字符串”型数据则设Excel单元格为“文本”型
MySheet.Columns[iCol].NumberFormatLocal := '@';
end;
Inc(iRow);
end;
iCurRow := 1;
while (not Grid.DataSource.DataSet.Eof and not ShowProgress) or
(not Grid.DataSource.DataSet.Eof and ShowProgress and (Button.Tag = 0)) do
begin
for iCol := 1 to Grid.FieldCount do
begin
Application.ProcessMessages;
if Grid.Fields[iCol - 1].IsBlob then
varCells[iCurRow, iCol] := '二进制数据'
else varCells[iCurRow, iCol] := Grid.Fields[iCol-1].AsString;
end;
Inc(iRow);
Inc(iCurRow);
if ShowProgress then
ProgressBar.Position := ProgressBar.Position + 1;
Application.ProcessMessages;
Grid.DataSource.DataSet.Next;
if (iCurRow > iVarCount) or (iRow > MaxPageRowCount + 1) then
begin
Application.ProcessMessages;
Break;
end;
end;
Cell1 := MyCells.Item[iRow - iCurRow + 1, 1];
Cell2 := MyCells.Item[iRow - 1,Grid.FieldCount];
Range := MySheet.Range[Cell1 ,Cell2];
Range.Value := varCells;
MySheet.Columns.AutoFit;
Cell1 := Unassigned;
Cell2 := Unassigned;
Range := Unassigned;
Application.ProcessMessages;
end;
if (ShowProgress and (Button.Tag = 0)) or not ShowProgress then
MySheet.saveas(FileName);
MyCells := Unassigned;
varCells := Unassigned;
Excel.WorkBooks[1].Saved := True;
MySheet.application.quit;
Excel.quit;
Excel := Unassigned;
if CurPos <> nil then
begin
Grid.DataSource.DataSet.GotoBookmark(CurPos);
Grid.DataSource.DataSet.FreeBookmark(CurPos);
end;
Grid.DataSource.DataSet.EnableControls;
if ProgressForm <> nil then
ProgressForm.Free;
end;
end;