Delphi下一个封装较为完整的DBGrid->Excel类

简介:
unit DBGridEhToExcel; 

interface 
uses 
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
Dialogs, DB, ComCtrls, ExtCtrls, StdCtrls, Gauges, DBGridEh, ShellApi; 

type 
TTitleCell = array of array of String; 

//分解DBGridEh的标题 
TDBGridEhTitle = class 
private 
   FDBGridEh: TDBGridEh;  //对应DBGridEh 
   FColumnCount: integer; //DBGridEh列数(指visible为True的列数) 
   FRowCount: integer;    //DBGridEh多表头层数(没有多表头则层数为1) 
   procedure SetDBGridEh(const Value: TDBGridEh); 
   function GetTitleRow: integer;    //获取DBGridEh多表头层数 
   function GetTitleColumn: integer; //获取DBGridEh列数 
public 
   //分解DBGridEh标题,由TitleCell二维动态数组返回 
   procedure GetTitleData(var TitleCell: TTitleCell); 
published 
   property DBGridEh: TDBGridEh read FDBGridEh write SetDBGridEh; 
   property ColumnCount: integer read FColumnCount; 
   property RowCount: integer read FRowCount; 
end; 

TDBGridEhToExcel = class(TComponent) 
private 
   FCol: integer; 
   FRow: integer; 
   FProgressForm: TForm;                                  {进度窗体} 
   FGauge: TGauge;                                        {进度条} 
   Stream: TStream;                                       {输出文件流} 
   FBookMark: TBookmark;                                   
   FShowProgress: Boolean;                                {是否显示进度窗体} 
   FDBGridEh: TDBGridEh; 
   FBeginDate: TCaption;                                  {开始日期} 
   FTitleName: TCaption;                                  {Excel文件标题} 
   FEndDate: TCaption;                                    {结束日期} 
   FUserName: TCaption;                                   {制表人} 
   FFileName: String;                                     {保存文件名} 
   procedure SetShowProgress(const Value: Boolean); 
   procedure SetDBGridEh(const Value: TDBGridEh); 
   procedure SetBeginDate(const Value: TCaption); 
   procedure SetEndDate(const Value: TCaption); 
   procedure SetTitleName(const Value: TCaption); 
   procedure SetUserName(const Value: TCaption); 
   procedure SetFileName(const Value: String);     

   procedure IncColRow; 
   procedure WriteBlankCell;                              {写空单元格} 
   {写数字单元格} 
   procedure WriteFloatCell(const AValue: Double; const IncStatus: Boolean=True); 
   {写整型单元格} 
   procedure WriteIntegerCell(const AValue: Integer; const IncStatus: Boolean=True); 
   {写字符单元格} 
   procedure WriteStringCell(const AValue: string; const IncStatus: Boolean=True); 
   procedure WritePrefix; 
   procedure WriteSuffix; 
   procedure WriteHeader;                                 {输出Excel标题} 
   procedure WriteTitle;                                  {输出Excel列标题} 
   procedure WriteDataCell;                               {输出数据集内容} 
   procedure WriteFooter;                                 {输出DBGridEh表脚} 
   procedure SaveStream(aStream: TStream); 
   procedure CreateProcessForm(AOwner: TComponent);       {生成进度窗体} 
   {根据表格修改数据集字段顺序及字段中文标题} 
   procedure SetDataSetCrossIndexDBGridEh; 
public 
   constructor Create(AOwner: TComponent); override; 
   destructor Destroy; override; 
   procedure ExportToExcel; {输出Excel文件} 
published 
   property DBGridEh: TDBGridEh read FDBGridEh write SetDBGridEh; 
   property ShowProgress: Boolean read FShowProgress write SetShowProgress; 
   property TitleName: TCaption read FTitleName write SetTitleName; 
   property BeginDate: TCaption read FBeginDate write SetBeginDate; 
   property EndDate: TCaption read FEndDate write SetEndDate; 
   property UserName: TCaption read FUserName write SetUserName; 
   property FileName: String read FFileName write SetFileName; 
end; 

var 
CXlsBof: array[0..5] of Word = (9, 8, 0, , 0, 0); 
CXlsEof: array[0..1] of Word = ({post.content}A, 00); 
CXlsLabel: array[0..5] of Word = (4, 0, 0, 0, 0, 0); 
CXlsNumber: array[0..4] of Word = (3, 14, 0, 0, 0); 
CXlsRk: array[0..4] of Word = (E, 10, 0, 0, 0); 
CXlsBlank: array[0..4] of Word = (1, 6, 0, 0, ); 

implementation 
{ TDBGridEhTitle } 


function TDBGridEhTitle.GetTitleColumn: integer; 
var 
i, ColumnCount: integer; 
begin 
ColumnCount := 0; 
for i := 0 to DBGridEh.Columns.Count - 1 do 
begin 
   if DBGridEh.Columns[i].Visible then 
     Inc(ColumnCount); 
end; 

Result := ColumnCount; 
end; 

procedure TDBGridEhTitle.GetTitleData(var TitleCell: TTitleCell); 
var 
i, Row, Col: integer; 
Caption: String; 
begin 
FColumnCount := GetTitleColumn; 
FRowCount := GetTitleRow; 
SetLength(TitleCell,FColumnCount,FRowCount); 
Row := 0; 
for i := 0 to DBGridEh.Columns.Count - 1 do 
begin 
   if DBGridEh.Columns[i].Visible then 
   begin 
     Col := 0; 
     Caption := DBGridEh.Columns[i].Title.Caption; 
     while POS('|', Caption) > 0 do 
     begin 
       TitleCell[Row,Col] := Copy(Caption, 1, Pos('|',Caption)-1); 
       Caption := Copy(Caption,Pos('|', Caption)+1, Length(Caption)); 
       Inc(Col); 
     end; 
     TitleCell[Row, Col] := Caption; 
     Inc(Row); 
   end; 
end; 
end; 

function TDBGridEhTitle.GetTitleRow: integer; 
var 
i, j: integer; 
MaxRow, Row: integer; 
begin 
MaxRow := 1; 
for i := 0 to DBGridEh.Columns.Count - 1 do 
begin 
   Row := 1; 
   for j := 0 to Length(DBGridEh.Columns[i].Title.Caption) do 
   begin 
     if DBGridEh.Columns[i].Title.Caption[j] = '|' then 
       Inc(Row); 
   end; 

   if MaxRow < Row then 
     MaxRow :=  Row; 
end; 

Result := MaxRow; 
end; 

procedure TDBGridEhTitle.SetDBGridEh(const Value: TDBGridEh); 
begin 
FDBGridEh := Value; 
end; 

{ TDBGridEhToExcel } 

constructor TDBGridEhToExcel.Create(AOwner: TComponent); 
begin 
inherited Create(AOwner); 
FShowProgress := True; 
end; 

procedure TDBGridEhToExcel.SetShowProgress(const Value: Boolean); 
begin 
FShowProgress := Value; 
end; 

procedure TDBGridEhToExcel.SetDBGridEh(const Value: TDBGridEh); 
begin 
FDBGridEh := Value; 
end; 

procedure TDBGridEhToExcel.SetBeginDate(const Value: TCaption); 
begin 
FBeginDate := Value; 
end; 

procedure TDBGridEhToExcel.SetEndDate(const Value: TCaption); 
begin 
FEndDate := Value; 
end; 

procedure TDBGridEhToExcel.SetTitleName(const Value: TCaption); 
begin 
FTitleName := Value; 
end; 

procedure TDBGridEhToExcel.SetUserName(const Value: TCaption); 
begin 
FUserName := Value; 
end; 

procedure TDBGridEhToExcel.SetFileName(const Value: String); 
begin 
FFileName := Value; 
end; 

procedure TDBGridEhToExcel.IncColRow; 
begin 
if FCol = DBGridEh.DataSource.DataSet.FieldCount - 1 then 
begin 
   Inc(FRow); 
   FCol := 0; 
end 
else 
   Inc(FCol); 
end; 

procedure TDBGridEhToExcel.WriteBlankCell; 
begin 
CXlsBlank[2] := FRow; 
CXlsBlank[3] := FCol; 
Stream.WriteBuffer(CXlsBlank, SizeOf(CXlsBlank)); 
IncColRow; 
end; 

procedure TDBGridEhToExcel.WriteFloatCell(const AValue: Double; const IncStatus: Boolean=True); 
begin 
CXlsNumber[2] := FRow; 
CXlsNumber[3] := FCol; 
Stream.WriteBuffer(CXlsNumber, SizeOf(CXlsNumber)); 
Stream.WriteBuffer(AValue, 8); 

if IncStatus then 
   IncColRow; 
end; 

procedure TDBGridEhToExcel.WriteIntegerCell(const AValue: Integer; const IncStatus: Boolean=True); 
var 
V: Integer; 
begin 
CXlsRk[2] := FRow; 
CXlsRk[3] := FCol; 
Stream.WriteBuffer(CXlsRk, SizeOf(CXlsRk)); 
V := (AValue Shl 2) Or 2; 
Stream.WriteBuffer(V, 4); 

if IncStatus then 
   IncColRow; 
end; 

procedure TDBGridEhToExcel.WriteStringCell(const AValue: string; const IncStatus: Boolean=True); 
var 
L: integer; 
begin 
L := Length(AValue); 
CXlsLabel[1] := 8 + L; 
CXlsLabel[2] := FRow; 
CXlsLabel[3] := FCol; 
CXlsLabel[5] := L; 
Stream.WriteBuffer(CXlsLabel, SizeOf(CXlsLabel)); 
Stream.WriteBuffer(Pointer(AValue)^, L); 

if IncStatus then 
   IncColRow; 
end; 

procedure TDBGridEhToExcel.WritePrefix; 
begin 
Stream.WriteBuffer(CXlsBof, SizeOf(CXlsBof)); 
end; 

procedure TDBGridEhToExcel.WriteSuffix; 
begin 
Stream.WriteBuffer(CXlsEof, SizeOf(CXlsEof)); 
end; 

procedure TDBGridEhToExcel.WriteHeader; 
var 
OpName, OpDate: String; 
begin 
//标题 
FCol := 3; 
WriteStringCell(TitleName,False); 
FCol := 0; 

Inc(FRow); 

if Trim(BeginDate) <> '' then 
begin 
   //开始日期 
   FCol := 0; 
   WriteStringCell(BeginDate,False); 
   FCol := 0 
end; 

if Trim(EndDate) <> '' then 
begin 
   //结束日期 
   FCol := 5; 
   WriteStringCell(EndDate,False); 
   FCol := 0; 
end; 

if (Trim(BeginDate) <> '') or (Trim(EndDate) <> '') then 
   Inc(FRow); 

//制表人 
OpName := '制表人:' + UserName; 
FCol := 0; 
WriteStringCell(OpName,False); 
FCol := 0; 

//制表时间 
OpDate := '制表时间:' + DateTimeToStr(Now); 
FCol := 5; 
WriteStringCell(OpDate,False); 
FCol := 0; 

Inc(FRow);   
end; 

procedure TDBGridEhToExcel.WriteTitle; 
var 
i, j: integer; 
DBGridEhTitle: TDBGridEhTitle; 
TitleCell: TTitleCell; 
begin 
DBGridEhTitle := TDBGridEhTitle.Create; 
try 
   DBGridEhTitle.DBGridEh := FDBGridEh; 
   DBGridEhTitle.GetTitleData(TitleCell); 

   try 
     for i := 0 to DBGridEhTitle.RowCount - 1 do 
     begin 
       for j := 0 to DBGridEhTitle.ColumnCount - 1 do 
       begin 
         FCol := j; 
         WriteStringCell(TitleCell[j,i],False); 
       end; 
       Inc(FRow); 
     end; 
     FCol := 0; 
   except 

   end; 
finally 
   DBGridEhTitle.Free; 
end; 
end; 


procedure TDBGridEhToExcel.WriteDataCell; 
var 
i: integer; 
begin 
DBGridEh.DataSource.DataSet.DisableControls; 
FBookMark := DBGridEh.DataSource.DataSet.GetBookmark; 
try 
   DBGridEh.DataSource.DataSet.First; 
   while not DBGridEh.DataSource.DataSet.Eof do 
   begin 
     for i := 0 to DBGridEh.DataSource.DataSet.FieldCount - 1 do 
     begin 
       if DBGridEh.DataSource.DataSet.Fields[i].IsNull or (not DBGridEh.DataSource.DataSet.Fields[i].Visible) then 
         WriteBlankCell 
       else 
       begin 
         case DBGridEh.DataSource.DataSet.Fields[i].DataType of 
           ftSmallint, ftInteger, ftWord, ftAutoInc, ftBytes: 
             WriteIntegerCell(DBGridEh.DataSource.DataSet.Fields[i].AsInteger); 
           ftFloat, ftCurrency, ftBCD: 
             WriteFloatCell(DBGridEh.DataSource.DataSet.Fields[i].AsFloat); 
         else 
           if DBGridEh.DataSource.DataSet.Fields[i] Is TBlobfield then  // 此类型的字段(图像等)暂无法读取显示 
             WriteStringCell('') 
           else 
             WriteStringCell(DBGridEh.DataSource.DataSet.Fields[i].AsString); 
         end; 
       end; 
     end; 

     //显示进度条进度过程 
     if ShowProgress then 
     begin 
       FGauge.Progress := DBGridEh.DataSource.DataSet.RecNo; 
       FGauge.Refresh; 
     end; 

     DBGridEh.DataSource.DataSet.Next; 
   end; 

finally 
   if DBGridEh.DataSource.DataSet.BookmarkValid(FBookMark) then 
   DBGridEh.DataSource.DataSet.GotoBookmark(FBookMark); 

   DBGridEh.DataSource.DataSet.EnableControls; 
end; 
end; 

procedure TDBGridEhToExcel.WriteFooter; 
var 
i, j: integer; 
begin 
if DBGridEh.FooterRowCount = 0 then exit; 

FCol := 0; 
if DBGridEh.FooterRowCount = 1 then 
begin 
   for i := 0 to DBGridEh.Columns.Count - 1 do 
   begin 
     if DBGridEh.Columns[i].Visible then 
     begin 
       WriteStringCell(DBGridEh.Columns[i].Footer.Value,False); 
       Inc(FCol); 
     end; 
   end; 
end 
else if DBGridEh.FooterRowCount > 1 then 
begin 
   for i := 0 to DBGridEh.Columns.Count - 1 do 
   begin 
     if DBGridEh.Columns[i].Visible then 
     begin 
       for j := 0 to DBGridEh.Columns[i].Footers.Count - 1 do 
       begin 
         WriteStringCell(DBGridEh.Columns[i].Footers[j].Value ,False); 
         Inc(FRow); 
       end; 
       Inc(FCol); 
       FRow := FRow - DBGridEh.Columns[i].Footers.Count; 
     end; 
   end; 
end; 
FCol := 0; 
end; 

procedure TDBGridEhToExcel.SaveStream(aStream: TStream); 
begin 
FCol := 0; 
FRow := 0; 
Stream := aStream; 

//输出前缀 
WritePrefix; 

//输出表格标题 
WriteHeader; 

//输出列标题 
WriteTitle; 

//输出数据集内容 
WriteDataCell; 

//输出DBGridEh表脚 
WriteFooter; 

//输出后缀 
WriteSuffix; 
end; 

procedure TDBGridEhToExcel.ExportToExcel; 
var 
FileStream: TFileStream; 
Msg: String; 
begin 
//如果数据集为空或没有打开则退出 
if (DBGridEh.DataSource.DataSet.IsEmpty) or (not DBGridEh.DataSource.DataSet.Active) then 
   exit; 

//如果保存的文件名为空则退出 
if Trim(FileName) = '' then 
   exit; 
    
//根据表格修改数据集字段顺序及字段中文标题 
SetDataSetCrossIndexDBGridEh; 

Screen.Cursor := crHourGlass; 
try 
   try 
     if FileExists(FileName) then 
     begin 
       Msg := '已存在文件(' + FileName + '),是否覆盖?'; 
       if Application.MessageBox(PChar(Msg),'提示',MB_YESNO+MB_ICONQUESTION+MB_DEFBUTTON2) = IDYES then 
       begin 
         //删除文件 
         DeleteFile(FileName) 
       end 
       else 
         exit; 
     end; 

     //显示进度窗体 
     if ShowProgress then 
       CreateProcessForm(nil); 
        
     FileStream := TFileStream.Create(FileName, fmCreate); 
     try 
       //输出文件 
       SaveStream(FileStream); 
     finally 
       FileStream.Free; 
     end; 
      
     //打开Excel文件 
     ShellExecute(0, 'Open', PChar(FileName), nil, nil, SW_SHOW); 
   except 

   end; 
finally 
   if ShowProgress then 
     FreeAndNil(FProgressForm); 
   Screen.Cursor := crDefault; 
end; 
end; 

destructor TDBGridEhToExcel.Destroy; 
begin 
inherited Destroy; 
end; 

procedure TDBGridEhToExcel.CreateProcessForm(AOwner: TComponent); 
var 
Panel: TPanel; 
Prompt: TLabel;                                           {提示的标签} 
begin 
if Assigned(FProgressForm) then 
   exit; 

FProgressForm := TForm.Create(AOwner); 
with FProgressForm do 
begin 
   try 
     Font.Name := '宋体';                                  {设置字体} 
     Font.Size := 9; 
     BorderStyle := bsNone; 
     Width := 300; 
     Height := 100; 
     BorderWidth := 1; 
     Color := clBlack; 
     Position := poScreenCenter; 

     Panel := TPanel.Create(FProgressForm); 
     with Panel do 
     begin 
       Parent := FProgressForm; 
       Align := alClient; 
       BevelInner := bvNone; 
       BevelOuter := bvRaised; 
       Caption := ''; 
     end; 

     Prompt := TLabel.Create(Panel); 
     with Prompt do 
     begin 
       Parent := Panel; 
       AutoSize := True; 
       Left := 25; 
       Top := 25; 
       Caption := '正在导出数据,请稍候......'; 
       Font.Style := [fsBold]; 
     end; 

     FGauge := TGauge.Create(Panel); 
     with FGauge do 
     begin 
       Parent := Panel; 
       ForeColor := clBlue; 
       Left := 20; 
       Top := 50; 
       Height := 13; 
       Width := 260; 
       MinValue := 0; 
       MaxValue := DBGridEh.DataSource.DataSet.RecordCount; 
     end; 
   except 

   end; 
end; 

FProgressForm.Show; 
FProgressForm.Update; 
end; 

procedure TDBGridEhToExcel.SetDataSetCrossIndexDBGridEh; 
var 
i: integer; 
begin 
for i := 0 to DBGridEh.Columns.Count - 1 do 
begin 
   DBGridEh.DataSource.DataSet.FieldByName(DBGridEh.Columns.Items[i].FieldName).Index := i; 
   DBGridEh.DataSource.DataSet.FieldByName(DBGridEh.Columns.Items[i].FieldName).DisplayLabel 
     := DBGridEh.Columns.Items[i].Title.Caption; 
   DBGridEh.DataSource.DataSet.FieldByName(DBGridEh.Columns.Items[i].FieldName).Visible := 
     DBGridEh.Columns.Items[i].Visible; 
end; 

for i := 0 to DBGridEh.DataSource.DataSet.FieldCount - 1 do 
begin 
   if POS('*****',DBGridEh.DataSource.DataSet.Fields[i].DisplayLabel) > 0 then 
     DBGridEh.DataSource.DataSet.Fields[i].Visible := False; 
end;   
end; 

end. 


/*****************************************************************/ 

调用的例子 

var 
DBGridEhToExcel: TDBGridEhToExcel; 
begin 
DBGridEhToExcel := TDBGridEhToExcel.Create(nil); 
try 
   DBGridEhToExcel.TitleName := '测试测试测试测试测试测试测试'; 
   DBGridEhToExcel.BeginDate := '开始日期:2005-07-01'; 
   DBGridEhToExcel.EndDate := '结束日期:2005-07-18'; 
   DBGridEhToExcel.UserName := '系统管理员'; 
   DBGridEhToExcel.DBGridEh := DBGridEh1; 
   DBGridEhToExcel.ShowProgress := True; 
   DBGridEhToExcel.FileName := 'c:3.xls'; 
   DBGridEhToExcel.ExportToExcel; 
finally 
   DBGridEhToExcel.Free; 
end; 
end;




    本文转自 OldHawk  博客园博客,原文链接:http://www.cnblogs.com/taobataoma/archive/2007/06/13/781417.html,如需转载请自行联系原作者


相关文章
|
7月前
|
前端开发 Shell API
强大的类excel插件,handsontable的简单应用
强大的类excel插件,handsontable的简单应用
289 1
|
7月前
|
easyexcel 数据库
公司大佬对excel导入、导出的封装,那叫一个秒啊
封装公司统一使用的组件的主要目标是为了简化开发人员的调用流程,避免各个项目组重复集成和编写不规范的代码。文中提到对阿里EasyExcel进行了二次封装,提供了导入和导出功能,并支持模板的导入和导出。此外,还处理了读取数据与实际保存数据不一致的情况,通过提供自定义转换器来解决。
318 0
|
7月前
|
Python
python使用tkinter库,封装操作excel为GUI程序
python使用tkinter库,封装操作excel为GUI程序
387 0
|
7月前
|
Java easyexcel 数据库连接
SpringBoot使用EasyExcel将Excel数据直接转换为类对象
SpringBoot使用EasyExcel将Excel数据直接转换为类对象
324 0
|
程序员
QT快速操作Excel的实现介绍及操作类封装
QT快速操作Excel的实现介绍及操作类封装
QT快速操作Excel的实现介绍及操作类封装
|
移动开发 Java fastjson
Spring Boot 我随手封装了一个万能的 Excel 导出工具,传什么都能导出!
Spring Boot 我随手封装了一个万能的 Excel 导出工具,传什么都能导出!
Spring Boot 我随手封装了一个万能的 Excel 导出工具,传什么都能导出!
|
前端开发 JavaScript Java
打造类 EXCEL 的公式体系
打造类 EXCEL 的公式体系
184 0
|
消息中间件 JavaScript 小程序
ngBoot 我随手封装了一个万能的导出excel工具,传什么都能导出 下
ngBoot 我随手封装了一个万能的导出excel工具,传什么都能导出 下
|
JavaScript 小程序 Java
ngBoot 我随手封装了一个万能的导出excel工具,传什么都能导出 上
ngBoot 我随手封装了一个万能的导出excel工具,传什么都能导出 上
|
Java
java 导出excel封装了一个简单的导出方法。
java 导出excel封装了一个简单的导出方法。
103 0