一个通用的Delphi数据导出到Excel函数

一个通用的Delphi数据导出到Excel函数

(2008-05-09 21:10:07)

关键字:delphi 对Excel编程,TDataSet(Tquery,TTabe)导到Excel,如何设置Excel字体、文本对齐方式,如何设置单元格边框,如何合并单元格,如何Excel打印设置,如何设置单元格为文本格式

主要功能:

1.数据集导出到Excel函数

2.自动设置列宽

3.自动调节适应A4纸张

4.具有打开Excel、打印预览、直接打印选项

unit ExcelReport;

interface

uses

SysUtils, Variants, Controls, Forms, Dialogs, ComObj, ComCtrls, DB, excel2000,

StdCtrls, Graphics, Windows, Grids;

{**************************************************************************************

数据集导出到Excel函数,自动设置列宽,自动调节适应A4纸张

Columns:可以是DataSet的Fields,ListView的Columns,StringGrid之一

DataSet:数据集

Caption:大标题,

SubCaption:子标题,

LeftCaption:左标题,

CenterCaption:中标题

RightCaption:右标题

Flag:1:预览,2:直接打印,0:打开Excel编辑

ColAutoSize:是否允许自动列宽

**************************************************************************************}

procedure DataSetToExcel(Columns: TObject; DataSet: TDataSet; Caption: String = '';

SubCaption: String = ''; LeftCaption: String = '';

CenterCaption: String = ''; RightCaption: String = '';

Flag: Integer = 1; ColAutoSize: Boolean = True);

implementation

procedure DataSetToExcel(Columns: TObject; DataSet: TDataSet; Caption: String = '';

SubCaption: String = ''; LeftCaption: String = '';

CenterCaption: String = ''; RightCaption: String = '';

Flag: Integer = 1; ColAutoSize: Boolean = True);

const

MaxColWidth = 80;

RowCaption = 1;

RowUse = 5;

FontSizeCaption = 15;

FontSizeSubCaption = 10;

FontSizeLeftCaption = 12;

FontSizeCenterCaption = 12;

FontSizeRightCaption = 12;

FontSizeColumns = 10;

FontSizeData = 10;

FontNameCaption = '楷体';

FontNameSubCaption = '宋体';

FontNameLeftCaption = '宋体';

FontNameCenterCaption = '宋体';

FontNameRightCaption = '宋体';

FontNameColumns = '宋体';

FontNameData = '宋体';

TextAlignLeft = 2;

TextAlignCenter = 3;

TextAlignRight = 4;

TextAlignTop = 1;

TextAlignVCenter = 2;

TextAlignBottom = 3;

var

Excel, Sheet: Variant;

RowIndex: Integer;

ColSum: Integer;

Form: TForm;

lb: TLabel;

function GetExcel(): Integer;

begin

Result := DataSet.RecordCount + RowUse;

if (Result > 65536 ) then

begin

if (MessageDlg(' 需要导出的数据过大,Excel最大只能容纳65536行,'+

#13'将会截断超过部分,是否还要继续?',

mtConfirmation, [mbYes, mbNo], 0) = mrNo) then

begin

Result := 0;

exit;

end else

Result := 65536;

end;

try

Excel := CreateOleobject('Excel.Application');

except

ShowMessage(#13' Excel没有正确安装!');

end;

end;

function GetColumnsWidth(): Integer;

var

i: Integer;

begin

Result := 0;

for i := 1 to ColSum do

Result := Result + Sheet.Columns[i].ColumnWidth;

Result := Excel.InchesToPoints((Result * 2.2862) / 25.4);

end;

procedure SetColumns( Columns: TListColumns); overload;

var

i: Integer;

s: String;

begin

for i := 0 to (Columns.Count - 1) do

begin

s := Columns[i].Caption;

Sheet.Columns[i + 1].ColumnWidth := Length(s);

Sheet.Cells[RowIndex, i + 1].value := s;

end;

end;

procedure SetColumns( Columns: TFields); overload;

var

i: Integer;

s: String;

begin

for i := 0 to (Columns.Count - 1) do

begin

s := Columns[i].FieldName;

Sheet.Columns[i + 1].ColumnWidth := Length(s);

Sheet.Cells[RowIndex, i + 1].value := s;

end;

end;

procedure SetColumns( Columns: TStringGrid); overload;

var

i: Integer;

s: String;

begin

for i := 1 to (Columns.ColCount - 1) do

begin

s := Columns.Cells[i, 0];

Sheet.Columns[i].ColumnWidth := Length(s);

Sheet.Cells[RowIndex, i].value := s;

end;

end;

procedure DoDataSetToExcel();

function GetDateTimeStr(DT: TDateTime): String;

var

nDT: Integer;

begin

Result := TimeToStr(DT);

nDT := Trunc(DT);

if nDT < 1000 then

begin

if nDT - 2 >= 1 then

Result := IntToStr(nDT - 2) + '天' + Result;

end else

Result := DateToStr(DT) + ' ' + Result;

end;

var

i, RowEnd, Len: Integer;

s: String;

begin

RowEnd := DataSet.RecordCount + RowIndex - 1;

if RowEnd > 65536 then

RowEnd := 65536;

DataSet.First();

while not DataSet.Eof do

begin

for i := 0 to DataSet.Fields.Count - 1 do

begin

if DataSet.Fields[i].DataType in [ftDateTime, ftDate, ftTime] then

begin

if DataSet.Fields[i].IsNull then

s := ''

else

s := GetDateTimeStr(DataSet.Fields[i].AsDateTime);

end else

s := DataSet.Fields[i].AsString;

if ColAutoSize then

begin

Len := Length(s) - 1;

if Len > MaxColWidth then

Len := MaxColWidth;

if Sheet.Columns[i + 1].ColumnWidth < Len then

Sheet.Columns[i + 1].ColumnWidth := Len;

end;

Sheet.Cells[RowIndex, i + 1].value := s;

end;

if RowIndex = RowEnd then

break;

if RowIndex mod 10 = 0 then

begin

lb.Caption := Format('正在导出数据,已经完成:%d', [Trunc(RowIndex / RowEnd * 100)]) + '%';

Form.Update();

Application.ProcessMessages();

end;

RowIndex := RowIndex + 1;

DataSet.Next();

end;

lb.Caption := '数据导出完毕......';

Form.Update();

end;

function RowColToStr( R1, C1, R2, C2: Integer): String;

function ColToStr(C: Integer): String;

var

nDiv: Integer;

begin

Result := '';

if C > 26 then

begin

nDiv := C div 26;

C := (C mod 26);

if C = 0 then

begin

C := 26;

nDiv := nDiv - 1;

end;

Result := Char(Integer('A') + nDiv);

end;

Result := Result + Char(Integer('A') + C - 1);

end;

begin

Result := ColToStr(C1) + IntToStr(R1) + ':' + ColToStr(C2) + IntToStr(R2);

end;

var

Range, RangeFind: Variant;

RowEnd: Integer;

function RepString(FindStr, ReplacedStr: String): Boolean;

begin

Result := False;

RangeFind := Excel.Cells.Find(FindStr, EmptyParam, xlFormulas, xlPart, xlByRows, xlNext, False, False);

try

RowIndex := RangeFind.Row;

RangeFind.Select;

Excel.ActiveCell.value := ReplacedStr;

Result := True;

except

end;

end;

procedure SetFormat();

var

i: Integer;

begin

for i := 0 to DataSet.Fields.Count - 1 do

begin

case DataSet.Fields[i].DataType of

ftSmallint, ftInteger, ftWord, ftAutoInc, ftLargeint:

begin

Range := Sheet.Range[RowColToStr(RowIndex, i + 1, RowEnd, i + 1)];

Range.HorizontalAlignment := TextAlignRight;

//Range.NumberFormat := '#,##0;-#,##0';

end;

ftFloat:

begin

Range := Sheet.Range[RowColToStr(RowIndex, i + 1, RowEnd, i + 1)];

Range.HorizontalAlignment := TextAlignRight;

Range.NumberFormat := '#,##0.000000;-#,##0.00000';

end;

ftDate, ftTime, ftDateTime:

begin

Range := Sheet.Range[RowColToStr(RowIndex, i + 1, RowEnd, i + 1)];

Range.HorizontalAlignment := TextAlignRight;

Range.NumberFormatLocal := '@';

if DataSet.Fields[i].AsDateTime < 1000 then

Sheet.Columns[i + 1].ColumnWidth := 9.1

else

Sheet.Columns[i + 1].ColumnWidth := 17;

end;

end;

end;

end;

procedure CheckPageWidth();

var

PageW, WordW, BorderMargin: Integer;

tmp: Integer;

i: Integer;

ftmp: real;

begin

if (xlPaperA4 = Sheet.PageSetup.PaperSize) and (xlPortrait = Sheet.PageSetup.Orientation) then

begin

BorderMargin := Sheet.PageSetup.LeftMargin * 2;

WordW := GetColumnsWidth();

PageW := Excel.InchesToPoints(21 / 2.54);

if WordW > PageW - BorderMargin then

begin

Sheet.PageSetup.Orientation := xlLandscape;

PageW := Excel.InchesToPoints(29.7 / 2.54);

tmp := PageW - WordW - BorderMargin;

ftmp := tmp / WordW;

if (tmp < 0) and (ftmp >= -0.15) then

begin

ftmp := 1 + ftmp;

for i := 1 to ColSum do

Sheet.Columns[i].ColumnWidth := Sheet.Columns[i].ColumnWidth * ftmp;

end;

end;

end;

end;

var

Workbook: Variant;

CursorSave: TCursor;

ColCenter: Integer;

FileName: String;

begin

ColSum := DataSet.Fields.Count;

if ColSum = 0 then

begin

ShowMessage(#13' 数据表的列数为0,无法导出!');

exit;

end;

CursorSave := Screen.Cursor;

Form := TForm.Create(nil);

Form.BorderStyle := bsNone;

Form.FormStyle := fsStayOnTop;

Form.Width := 300;

Form.Height := 90;

Form.Left := (Screen.Width - Form.Width) div 2;

Form.Top := (Screen.Height - Form.Height) div 2;

lb := TLabel.Create(Form);

lb.Parent := Form;

lb.AutoSize := False;

lb.Left := 5;

lb.Top := 35;

lb.Width := 290;

lb.Height := 30;

lb.Font.Size := 10;

lb.Font.Color := clBlue;

Form.Show();

try

Screen.Cursor := crHourGlass;

lb.Caption := '正在创建Excel......';

Form.Update();

RowEnd := GetExcel();

if RowEnd > 0 then

begin

try

try

lb.Caption := '正在打开Excel......';

Form.Update();

FileName := ExtractFileDir(Application.ExeName) + '\' + Caption + '_模板.xls';

if FileExists(FileName) then

begin

FileName := ExtractFileDir(Application.ExeName) + '\' + Caption + '.xls';

CopyFile(PChar(ExtractFileDir(Application.ExeName) + '\' + Caption + '_模板.xls'), PChar(FileName), False) ;

end else

FileName := '';

if FileName <> '' then

begin

Workbook := Excel.Workbooks.Open(FileName)

end else

begin

Workbook := Excel.Workbooks.Add;

Excel.WorkSheets[1].Name := Caption;

end;

Excel.WorkSheets[1].Activate;

Sheet := Excel.Workbooks[1].WorkSheets[1];

Sheet.Cells.NumberFormatLocal := '@';

RowIndex := RowCaption;

ColCenter := (ColSum + 1) div 2;

lb.Caption := '正在设置标题......';

Form.Update();

Sheet.Range['A1:A1'].Select;

if Caption <> '' then

begin

//设置标题

if (FileName = '') or (not RepString('%标题%', Caption)) then

begin

Range := Sheet.Range[RowColToStr(RowIndex, 1, RowIndex, ColSum)];

Range.NumberFormatLocal := '@';

Range.HorizontalAlignment := TextAlignCenter;

Range.VerticalAlignment := TextAlignVCenter;

Range.Characters.Font.Name := FontNameCaption;

Range.Characters.Font.FontStyle := '加粗';

Range.Characters.Font.Size := FontSizeCaption;

Sheet.Cells[RowIndex, ColCenter].value := Caption;

Range.Merge;

end;

end;

if SubCaption <> '' then

begin

//设置子标题

if (FileName = '') or (not RepString('%子标题%', SubCaption)) then

begin

RowIndex := RowIndex + 1;

Range := Sheet.Range[RowColToStr(RowIndex, 1, RowIndex, ColSum)];

Range.HorizontalAlignment := TextAlignCenter;

Range.VerticalAlignment := TextAlignTop;

Range.Characters.Font.Name := FontNameSubCaption;

Range.Characters.Font.FontStyle := '加粗';

Range.Characters.Font.Size := FontSizeSubCaption;

Sheet.Cells[RowIndex, ColCenter].value := SubCaption;

Range.Merge; //合并

RowIndex := RowIndex + 1;

end;

end;

if (FileName = '') then

begin

Sheet.Rows[Format('%d:%d', [RowIndex, RowIndex])].Select;

Excel.Selection.RowHeight := 8;

RowIndex := RowIndex + 1;

end;

if LeftCaption <> '' then

begin

//设置左标题

if (FileName = '') or (not RepString('%左标题%', LeftCaption)) then

begin

//设置左标题

Range := Sheet.Range[RowColToStr(RowIndex, 1, RowIndex, 1)];

Range.HorizontalAlignment := TextAlignLeft;

Range.Characters.Font.Name := FontNameLeftCaption;

Range.Characters.Font.FontStyle := '加粗';

Range.Characters.Font.Size := FontSizeLeftCaption;

Sheet.Cells[RowIndex, 1].value := LeftCaption;

end;

end;

if CenterCaption <> '' then

begin

//设置中标题

if (FileName = '') or (not RepString('%中标题%', CenterCaption)) then

begin

Range := Sheet.Range[RowColToStr(RowIndex, ColCenter, RowIndex, ColCenter)];

Range.HorizontalAlignment := TextAlignCenter;

Range.Characters.Font.Name := FontNameCenterCaption;

Range.Characters.Font.FontStyle := '加粗';

Range.Characters.Font.Size := FontSizeCenterCaption;

Sheet.Cells[RowIndex, ColCenter].value := CenterCaption;

end;

end;

if RightCaption <> '' then

begin

//设置右标题

if (FileName = '') or (not RepString('%右标题%', RightCaption)) then

begin

Range := Sheet.Range[RowColToStr(RowIndex, ColSum, RowIndex, ColSum)];

Range.HorizontalAlignment := TextAlignRight;

Range.Characters.Font.Name := FontNameRightCaption;

Range.Characters.Font.FontStyle := '加粗';

Range.Characters.Font.Size := FontSizeRightCaption;

Sheet.Cells[RowIndex, ColSum].value := RightCaption;

end;

end;

if RowIndex <> RowCaption then

RowIndex := RowIndex + 1;

//设置栏目字体

Range := Sheet.Range[RowColToStr(RowIndex, 1, RowIndex, ColSum)];

Range.Select;

if (FileName <> '') and RepString('%栏目%', '') then

begin

Range.Characters.Font.Name := RangeFind.Characters.Font.Name;

Range.Characters.Font.Size := RangeFind.Characters.Font.Size;

Range.HorizontalAlignment := RangeFind.HorizontalAlignment;

Range.Characters.Font.FontStyle := RangeFind.Characters.Font.FontStyle;

Range.Borders[1].Weight := RangeFind.Borders[1].Weight;

Range.Borders[2].Weight := RangeFind.Borders[2].Weight;

Range.Borders[3].Weight := RangeFind.Borders[3].Weight;

Range.Borders[4].Weight := RangeFind.Borders[4].Weight;

end else

begin

Range.Characters.Font.Name := FontNameColumns;

Range.Characters.Font.Size := FontSizeColumns;

Range.HorizontalAlignment := TextAlignCenter;

Range.Characters.Font.FontStyle := '加粗';

Range.Borders[1].Weight := 2;

Range.Borders[2].Weight := 2;

Range.Borders[3].Weight := 2;

Range.Borders[4].Weight := 2;

end;

Sheet.PageSetup.PrintTitleRows := Format('$%d:$%d', [RowIndex, RowIndex]);

lb.Caption := '正在设置栏目和数据区字体......';

Form.Update();

//设置栏目文字

if Columns is TFields then

SetColumns(TFields(Columns))

else

if Columns is TStringGrid then

SetColumns(TStringGrid(Columns))

else

if Columns is TListColumns then

SetColumns(TListColumns(Columns));

RowIndex := RowIndex + 1;

//设置数据字体

Range := Sheet.Range[RowColToStr(RowIndex, 1, RowEnd, ColSum)];

Range.Select;

if (FileName <> '') and RepString('%数据%', '') then

begin

Range.Characters.Font.Name := RangeFind.Characters.Font.Name;

Range.Characters.Font.Size := RangeFind.Characters.Font.Size;

Range.HorizontalAlignment := RangeFind.HorizontalAlignment;

Range.Characters.Font.FontStyle := RangeFind.Characters.Font.FontStyle;

Range.Borders[1].Weight := RangeFind.Borders[1].Weight;

Range.Borders[2].Weight := RangeFind.Borders[2].Weight;

Range.Borders[3].Weight := RangeFind.Borders[3].Weight;

Range.Borders[4].Weight := RangeFind.Borders[4].Weight;

end else

begin

Range.Characters.Font.Name := FontNameData;

Range.Characters.Font.Size := FontSizeData;

Range.Borders[1].Weight := 2;

Range.Borders[2].Weight := 2;

Range.Borders[3].Weight := 2;

Range.Borders[4].Weight := 2;

end;

//设置数字栏显示格式

if FileName = '' then

SetFormat();

//加载数据到Excel

lb.Caption := '正在导出数据......';

Form.Update();

DoDataSetToExcel();

Sheet.Range['A1:A1'].Select;

if FileName = '' then

begin

Sheet.PageSetup.LeftMargin := Excel.InchesToPoints(0.590551181102362);//Excel.InchesToPoints(0.393700787401575);

Sheet.PageSetup.RightMargin := Sheet.PageSetup.LeftMargin;

Sheet.PageSetup.TopMargin := Sheet.PageSetup.LeftMargin;

Sheet.PageSetup.BottomMargin := Sheet.PageSetup.LeftMargin;

Sheet.PageSetup.CenterHorizontally := True;

Sheet.PageSetup.CenterVertically := True;

Sheet.PageSetup.CenterFooter := '第 &P 页,共 &N 页';

end;

CheckPageWidth();

case Flag of

1: //打印预览

begin

Excel.Visible := True;

Form.Hide();

Workbook.Saved := True;

Excel.DisplayAlerts := False;

Sheet.PrintPreview;

Excel.Visible := False;

Excel.Quit;

end;

2: //直接打印

begin

Form.Hide();

Sheet.PrintOut;

Workbook.Saved := True;

Excel.DisplayAlerts := False;

Excel.Quit;

end;

else //打开Excel编辑

Form.Hide();

Excel.Visible := True;

end;

except

Workbook.Saved := True;

Excel.DisplayAlerts := False;

Excel.Quit;

end;

finally

Excel := UnAssigned;

end;

end;

finally

lb.Destroy();

Form.Destroy();

Screen.Cursor := CursorSave;

end;

end;

end.