//首先感谢原作者,但当初在csdn上搜索到该单元时,就没原作者的信息(程序里的有些乱码的注释应该是原作者留下的吧?呵呵)
//有不足的地方还请各位看官多多指点哈 ^_^
(* Modify By 角落的青苔@2005/05/13
说明:增加导出过程中的回调功能(用户停止,进度条)
是否在第一行插入FieldName
改错:以前只能对word类型数值写入,DWord会Range Check error;已修正,见CellInteger
//这个单元原来的Col和Row刚好弄反了(已修正):-(
增加导出分页的功能,因为xls单页不能超过 65536 行(采用的笨办法,不知谁有好一点的方法吗?比如直接写标记表示分页?)
*)
unit UnitXLSFile;
interface
uses
Windows, Messages, Variants, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
DB,DBGrids, OleServer, Excel2000;
const _MSG_XLSWriterIsRuning='有其它任务正在导出数据,暂时不能执行该操作,请稍后重试!';
type
TUserCommand=(UserStop, UserNeedSave, UserNotSave, UserSkip, UserDoNothing);
TExportXls_CallBackProc = procedure(iPos:Real) of object;
TAtributCell = (acHidden,acLocked,acShaded,acBottomBorder,acTopBorder,
acRightBorder,acLeftBorder,acLeft,acCenter,acRight,acFill);
TSetOfAtribut = set of TatributCell;
TXLSWriter = class(TObject)
private
fstream:TFileStream;
procedure WriteWord(w:word);
procedure SetCellAtribut(value:TSetOfAtribut;var FAtribut:array of byte);
protected
procedure WriteBOF;
procedure WriteEOF;
procedure WriteDimension;
public
maxCols,maxRows:Word;
//add by 角落的青苔@2005/05/18
procedure CellInteger(vRow,vCol:word;aValue:Integer;vAtribut:TSetOfAtribut=[]);
procedure CellDouble(vRow,vCol:word;aValue:double;vAtribut:TSetOfAtribut=[]);
procedure CellStr(vRow,vCol:word;aValue:String;vAtribut:TSetOfAtribut=[]);
procedure WriteField(vRow,vCol:word;Field:TField);
constructor Create(vFileName:string;const vMaxCols:Integer=100;const vMaxRows:Integer=65534);
destructor Destroy;override;
end;
procedure DataSetToXLS(ds:TDataSet;fname:String);
//Add By 角落的青苔@2005/05/13 //只能导出最多65536条记录
procedure DBGridToXLS(Grid:TDBGrid;fname:String; bSetFieldName:Boolean;CallFunc:TExportXls_CallBackProc; bAskForStop:Boolean=True );
//Add By 角落的青苔@2005/05/19
//突破xls单页65536行的限制,把数据分成数页
function DBGridToXlsEx(Grid:TDBGrid;fname:String; bSetFieldName:Boolean;CallFunc:TExportXls_CallBackProc;const bAskForStop:Boolean=True; const bNeedUnite:Boolean=True ):Integer;
//将数个XLS合并成一个(分页),必须保证Path最后无'\'或'/',实际已经做成线程,以免程序无响应
procedure UniteSeveralXLSToOne(const TmpFlag, Path, FileName : String;const iStart, iEnd : Integer);
//procedure StringGridToXLS(grid:TStringGrid;fname:String);
var
G_UserCmd:TUserCommand;
G_XLSWriterIsRuning : Boolean; //是否有XLSWriter实例在运行,因为G_UserCmd是全局变量,防止被非法刷新
implementation
const
{BOF}
CBOF = $0009;
BIT_BIFF5 = $0800;
BOF_BIFF5 = CBOF or BIT_BIFF5;
{EOF}
BIFF_EOF = $000a;
{Document types}
DOCTYPE_XLS = $0010;
{Dimensions}
DIMENSIONS = $0000;
var
CXlsBof: array[0..5] of Word = ($809, 8, 0, $10, 0, 0);
CXlsEof: array[0..1] of Word = ($0A, 00);
CXlsLabel: array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
CXlsNumber: array[0..4] of Word = ($203, 14, 0, 0, 0);
CXlsRk: array[0..4] of Word = ($27E, 10, 0, 0, 0);
CXlsBlank: array[0..4] of Word = ($201, 6, 0, 0, $17);
type
//合并数个Xls为一个多页面xls的线程
TUniteSeveralXLSToOneThread = class(TThread)
private
TmpFlag : String;
Path : String;
FileName : String;
iStart : Integer;
iEnd : Integer;
protected
mCompleted : Boolean;
procedure Execute; override;
public
constructor Create(const _TmpFlag, _Path, _FileName:String;const _iStart, _iEnd : Integer);
destructor Destroy; override;
end;
//根据StrFlags在FullStr最后出现的位置,将FullStr分割成两部分,取得的两部分均不包含StrFlags
procedure SplitStrToTwoPartByLastFlag(const FullStr,StrFlags:String;var strLeft,strRight:String);
var iPos:Integer;
begin
iPos := LastDelimiter(StrFlags,FullStr);
strLeft := Copy(FullStr, 1, iPos-1);
strRight := Copy(FullStr, iPos+1, Length(FullStr)-iPos);
end;
constructor TUniteSeveralXLSToOneThread.Create(const _TmpFlag, _Path, _FileName:String;const _iStart, _iEnd : Integer);
begin
inherited Create(True);
TmpFlag := _TmpFlag;
Path := _Path;
FileName := _FileName;
iStart := _iStart;
iEnd := _iEnd;
mCompleted := False;
Resume();
end;
destructor TUniteSeveralXLSToOneThread.Destroy;
begin
inherited;
end;
procedure TUniteSeveralXLSToOneThread.Execute;
const
_HeadLetterOfXls:Array [1..52]of String //注意这里只定义了52列,需要增加就自己动手,最多256列
= ('A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM',
'AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ');
_XlsResCaption= 'FKULWJS_SKSLA_892x_RES';
_XlsTmpCaption= 'FKULWJS_SKSLA_892x_TMP';
var
XlsAppRes, XlsAppTmp: TExcelApplication;
wkBookRes, wkBookTmp : _WorkBook;
wkSheetRes, wkSheetTmp : _WorkSheet;
LCID_Res, LCID_Tmp:Integer;
Pos_LeftTop, Pos_RightBottom : String; //Xls中左上、右下位置
XlsAppHwnd:THandle;
bDontSave : Boolean;
i : Integer;
StrName,StrExt:String; //文件名及扩展名
begin
FreeOnTerminate := True;
if Terminated then Exit;
SplitStrToTwoPartByLastFlag(FileName, '.', StrName, StrExt);
try
Screen.Cursor := crHourGlass;
bDontSave := False;
XlsAppRes := TExcelApplication.Create(Nil);
with XlsAppRes do
begin
Connect;
Visible[0]:=False;
LCID_Res:=GetUserDefaultLCID();
DisplayAlerts[LCID_Res]:=False;
Caption:=_XlsResCaption;
wkBookRes:=WorkBooks.Add(EmptyParam,LCID_Res);
end;
XlsAppTmp := TExcelApplication.Create(Nil);
with XlsAppTmp do
begin
Connect;
Visible[0]:=False;
LCID_Tmp :=GetUserDefaultLCID();
DisplayAlerts[LCID_Tmp]:=False;
Caption:=_XlsTmpCaption;
end;
for i:=iStart to iEnd do
begin
if i<=3 then wkSheetRes:=wkBookRes.Sheets[i] as _WorkSheet
else
begin
wkBookRes.Sheets.Add(EmptyParam, wkSheetRes, 1, EmptyParam, LCID_Res);
wkSheetRes := wkBookRes.Sheets[i] as _WorkSheet;
end;
wkBookTmp:= XlsAppTmp.WorkBooks.Open(Path+'\'+TmpFlag+IntToStr(i)+FileName, EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,LCID_Tmp);
Pos_LeftTop := 'A1';
wkSheetTmp := XlsAppTmp.ActiveSheet as _WorkSheet;
Pos_RightBottom := _HeadLetterOfXls[wkSheetTmp.UsedRange[LCID_Tmp].Columns.Count]+IntToStr(wkSheetTmp.UsedRange[LCID_Tmp].Rows.Count);
XlsAppTmp.Range[Pos_LeftTop, Pos_RightBottom].Copy(EmptyParam);
wkSheetRes.Activate(LCID_Res);
wkSheetRes.Range[Pos_LeftTop, Pos_RightBottom].Select;
wkSheetRes.Paste(EmptyParam, EmptyParam, LCID_Res);
wkSheetRes.Columns.AutoFit;
wkSheetRes.Range['A1','A1'].Select;
wkSheetRes.Name := StrName+'_'+IntToStr(i);
end;
finally
try
(wkBookRes.Sheets[1] as _WorkSheet).Activate(LCID_Res);
wkBookRes.Close(Not(bDontSave) ,Path+'\'+FileName,EmptyParam,LCID_Res);
XlsAppRes.Quit;
XlsAppRes.Disconnect;
finally
//杀死未关闭的Excel进程
XlsAppHwnd := FindWindow( Nil,_XlsResCaption );
if XlsAppHwnd<>0 then SendMessage( XlsAppHwnd, WM_CLOSE, 0, 0);
end;
try
//wkBookTmp.Close(False ,Path+'\'+TmpFlag+IntToStr(i)+FileName,EmptyParam,LCID_Tmp);
XlsAppTmp.Quit;
XlsAppTmp.Disconnect;
finally
XlsAppHwnd := FindWindow( Nil,_XlsTmpCaption );
if XlsAppHwnd<>0 then SendMessage( XlsAppHwnd, WM_CLOSE, 0, 0);
//TerminateProcess(XlsAppHwnd,0);
end;
mCompleted := True;
Screen.Cursor := crDefault;
end;
end;
procedure DataSetToXLS(ds:TDataSet;fname:String);
var c,r:Integer;
xls:TXLSWriter;
begin
xls:=TXLSWriter.create(fname);
if ds.FieldCount > xls.maxcols then
xls.maxcols:=ds.fieldcount+1;
try
xls.writeBOF;
xls.WriteDimension;
for c:=0 to ds.FieldCount-1 do
xls.Cellstr(0,c,ds.Fields[c].DisplayLabel);
r:=1;
ds.first;
while (not ds.eof) and (r <= xls.maxrows) do begin
for c:=0 to ds.FieldCount-1 do
if ds.Fields[c].AsString<>'' then
xls.WriteField(r,c,ds.Fields[c]);
inc(r);
ds.next;
end;
xls.writeEOF;
finally
xls.free;
end;
end;
procedure DBGridToXLS(Grid:TDBGrid;fname:String; bSetFieldName:Boolean;CallFunc:TExportXls_CallBackProc; bAskForStop:Boolean=True);
var c,r,i :Integer;
xls:TXLSWriter;
nTotalCount, nCurrentCount : Integer;
bDontSave:Boolean;
begin
bDontSave := False;
Grid.DataSource.DataSet.DisableControls;
xls:=TXLSWriter.create(fname);
if Grid.FieldCount > xls.maxcols then
xls.maxcols:=Grid.fieldcount+1;
try
G_XLSWriterIsRuning := True;
xls.writeBOF;
xls.WriteDimension;
if bSetFieldName then
begin
for c:=0 to Grid.FieldCount-1 do
xls.Cellstr(0,c,Grid.Fields[c].FieldName);
r :=2;
end
else r:=1;
for c:=0 to Grid.FieldCount-1 do
xls.Cellstr(r-1,c,Grid.Fields[c].DisplayLabel);
nTotalCount := Grid.DataSource.DataSet.RecordCount;
nCurrentCount := 0;
bDontSave := False;
Grid.DataSource.DataSet.First;
for i:=0 to nTotalCount-1 do
begin
Application.ProcessMessages;
if r > xls.maxrows then Raise Exception.Create('导出的数据超过'+IntToStr(xls.maxrows)+'条记录,操作失败!');
Inc(nCurrentCount);
CallFunc(nCurrentCount/nTotalCount);
if G_UserCmd=UserStop then
begin
if bAskForStop then
case Application.MessageBox('您停止了导出数据,请问需要保存吗?(选择“取消”继续导出)','询问',MB_YESNOCANCEL) of
IDYES: Break;
IDNO: begin
bDontSave := True;
Raise Exception.Create('用户停止,导出数据未保存!');
end;
IDCANCEL: G_UserCmd := UserDoNothing;
end
else begin bDontSave := True; Raise Exception.Create('用户停止,导出数据未保存!'); end;
end;
for c:=0 to Grid.FieldCount-1 do
if (Grid.Fields[c].AsString<>'') then
xls.WriteField(r,c,Grid.Fields[c]);
inc(r);
Grid.DataSource.DataSet.Next;
end;
finally
xls.writeEOF;
xls.free;
if bDontSave then DeleteFile(fname);
Grid.DataSource.DataSet.EnableControls;
G_XLSWriterIsRuning := False;
end;
end;
//将数个XLS合并成一个(分页)
procedure UniteSeveralXLSToOne(const TmpFlag, Path, FileName : String;const iStart, iEnd : Integer);
const
_HeadLetterOfXls:Array [1..52]of String
= ('A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM',
'AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ');
_XlsResCaption= 'FKULWJS_SKSLA_892x_RES';
_XlsTmpCaption= 'FKULWJS_SKSLA_892x_TMP';
var
XlsAppRes, XlsAppTmp: TExcelApplication;
wkBookRes, wkBookTmp : _WorkBook;
wkSheetRes, wkSheetTmp : _WorkSheet;
LCID_Res, LCID_Tmp:Integer;
Pos_LeftTop, Pos_RightBottom : String; //Xls中左上、右下位置
XlsAppHwnd:THandle;
bDontSave : Boolean;
i : Integer;
StrName,StrExt:String; //文件名及扩展名
begin
SplitStrToTwoPartByLastFlag(FileName, '.', StrName, StrExt);
try
bDontSave := False;
XlsAppRes := TExcelApplication.Create(Nil);
with XlsAppRes do
begin
Connect;
Visible[0]:=False;
LCID_Res:=GetUserDefaultLCID();
DisplayAlerts[LCID_Res]:=False;
Caption:=_XlsResCaption;
wkBookRes:=WorkBooks.Add(EmptyParam,LCID_Res);
end;
XlsAppTmp := TExcelApplication.Create(Nil);
with XlsAppTmp do
begin
Connect;
Visible[0]:=False;
LCID_Tmp :=GetUserDefaultLCID();
DisplayAlerts[LCID_Tmp]:=False;
Caption:=_XlsTmpCaption;
end;
for i:=iStart to iEnd do
begin
if i<=3 then wkSheetRes:=wkBookRes.Sheets[i] as _WorkSheet
else
begin
wkBookRes.Sheets.Add(EmptyParam, wkSheetRes, 1, EmptyParam, LCID_Res);
wkSheetRes := wkBookRes.Sheets[i] as _WorkSheet;
end;
wkBookTmp:= XlsAppTmp.WorkBooks.Open(Path+'\'+TmpFlag+IntToStr(i)+FileName, EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyParam,LCID_Tmp);
Pos_LeftTop := 'A1';
wkSheetTmp := XlsAppTmp.ActiveSheet as _WorkSheet;
Pos_RightBottom := _HeadLetterOfXls[wkSheetTmp.UsedRange[LCID_Tmp].Columns.Count]+IntToStr(wkSheetTmp.UsedRange[LCID_Tmp].Rows.Count);
XlsAppTmp.Range[Pos_LeftTop, Pos_RightBottom].Copy(EmptyParam);
wkSheetRes.Activate(LCID_Res);
wkSheetRes.Range[Pos_LeftTop, Pos_RightBottom].Select;
wkSheetRes.Paste(EmptyParam, EmptyParam, LCID_Res);
wkSheetRes.Columns.AutoFit;
wkSheetRes.Range['A1','A1'].Select;
wkSheetRes.Name := StrName+'__'+IntToStr(i);
end;
finally
try
(wkBookRes.Sheets[1] as _WorkSheet).Activate(LCID_Res);
wkBookRes.Close(Not(bDontSave) ,Path+'\'+FileName,EmptyParam,LCID_Res);
XlsAppRes.Quit;
XlsAppRes.Disconnect;
finally
//杀死未关闭的Excel进程
XlsAppHwnd := FindWindow( Nil,_XlsResCaption );
if XlsAppHwnd<>0 then SendMessage( XlsAppHwnd, WM_CLOSE, 0, 0);
end;
try
//wkBookTmp.Saved[LCID_Tmp]:=True;
XlsAppTmp.Quit;
XlsAppTmp.Disconnect;
finally
XlsAppHwnd := FindWindow( Nil,_XlsTmpCaption );
if XlsAppHwnd<>0 then SendMessage( XlsAppHwnd, WM_CLOSE, 0, 0);
end;
end;
end;
function DBGridToXlsEx(Grid:TDBGrid;fname:String; bSetFieldName:Boolean;CallFunc:TExportXls_CallBackProc;const bAskForStop:Boolean; const bNeedUnite:Boolean ):Integer;
var
c,r,i :Integer;
xls:TXLSWriter;
nTotalCount, nCurrentCount : Integer;
bDontSave:Boolean;
nOneSheetMaxRecord : Integer;
Path, FileName, tmpFile:String;
bNotEof : Boolean;
begin
G_XLSWriterIsRuning := True;
Result := 0;
bDontSave := False;
nTotalCount := Grid.DataSource.DataSet.RecordCount;
nCurrentCount := 0;
SplitStrToTwoPartByLastFlag(fname,'\/',Path,FileName);
Grid.DataSource.DataSet.DisableControls;
bNotEof := True;
try
while bNotEof do
begin
Inc(Result);
tmpFile := Path+'\$$$'+IntToStr(Result)+FileName;
DeleteFile(tmpFile);
xls:=TXLSWriter.Create(tmpFile,Grid.FieldCount+1, 65530 ); //65530
if Grid.FieldCount > xls.maxCols then
xls.maxCols := Grid.FieldCount+1;
try
xls.WriteBOF;
xls.WriteDimension;
if bSetFieldName then
begin
for c:=0 to Grid.FieldCount-1 do
xls.Cellstr(0,c,Grid.Fields[c].FieldName);
r :=2;
end
else r:=1;
for c:=0 to Grid.FieldCount-1 do
xls.Cellstr(r-1,c,Grid.Fields[c].DisplayLabel);
Grid.DataSource.DataSet.First;
Grid.DataSource.DataSet.MoveBy(nCurrentCount);
if nTotalCount-nCurrentCount>xls.maxrows then nOneSheetMaxRecord := xls.maxRows
else nOneSheetMaxRecord := nTotalCount-nCurrentCount;
for i:=0 to nOneSheetMaxRecord-1 do
begin
Application.ProcessMessages;
Inc(nCurrentCount);
CallFunc(nCurrentCount/nTotalCount);
if G_UserCmd=UserStop then
begin
if bAskForStop then
case Application.MessageBox('您停止了导出数据,请问需要保存吗?(选择“取消”继续导出)','询问',MB_YESNOCANCEL) of
IDYES:begin
G_UserCmd := UserNeedSave;
Break;
end;
IDNO: begin
G_UserCmd := UserNotSave;
bDontSave := True;
Raise Exception.Create('用户停止,导出数据未保存!');
end;
IDCANCEL: G_UserCmd := UserDoNothing;
end
else begin bDontSave := True; Raise Exception.Create('用户停止,导出数据未保存!'); end;
end;
for c:=0 to Grid.FieldCount-1 do
if (Grid.Fields[c].AsString<>'') then
xls.WriteField(r,c,Grid.Fields[c]);
inc(r);
Grid.DataSource.DataSet.Next;
end;
xls.writeEOF;
finally
xls.Free;
end;
bNotEof := (Not Grid.DataSource.DataSet.Eof) and (G_UserCmd = UserDoNothing);
end; //Not Grid.DataSource.DataSet.Eof
finally
if bDontSave then
for i:=1 to Result do DeleteFile(Path+'\$$$'+IntToStr(i)+FileName);
Grid.DataSource.DataSet.EnableControls;
end;
if bNeedUnite and (Not bDontSave) then
begin
if Result=1 then
begin
DeleteFile(fname);
RenameFile(tmpFile, fname)
end
else
begin
with TUniteSeveralXLSToOneThread.Create('$$$', Path, FileName, 1, Result) do
begin
while Not mCompleted do
begin
Application.ProcessMessages;
Sleep(0);
end;
end;
for i:=1 to Result do DeleteFile(Path+'\$$$'+IntToStr(i)+FileName);
end;
end;
G_XLSWriterIsRuning := False;
end;
(*
procedure StringGridToXLS(grid:TStringGrid;fname:String);
var c,r,rMax:Integer;
xls:TXLSWriter;
begin
xls:=TXLSWriter.create(fname);
rMax:=grid.RowCount;
if grid.ColCount > xls.maxcols then
xls.maxcols:=grid.ColCount+1;
if rMax > xls.maxrows then // ¦¹®æ¦¡³Ì¦h¥u¯à¦s 65535 Rows
rMax:=xls.maxrows;
try
xls.writeBOF;
xls.WriteDimension;
for c:=0 to grid.ColCount-1 do
for r:=0 to rMax-1 do
xls.Cellstr(r,c,grid.Cells[c,r]);
xls.writeEOF;
finally
xls.free;
end;
end;
*)
{ TXLSWriter }
constructor TXLSWriter.Create(vFileName:string;const vMaxCols, vMaxRows:Integer);
begin
inherited create;
if FileExists(vFilename) then
fStream:=TFileStream.Create(vFilename,fmOpenWrite)
else
fStream:=TFileStream.Create(vFilename,fmCreate);
if vMaxCols<100 then maxCols := vMaxCols //modify by 角落的青苔@2005/05/19
else maxCols := 100;
if vMaxCols<65535 then maxRows := vMaxRows
else maxRows := 65535;
//maxCols:=100; // <2002-11-17> dllee Column À³¸Ó¬O¤£¥i¯à¤j©ó 65535, ©Ò¥H¤£¦A³B²z
//maxRows:=65530;//65535; // <2002-11-17> dllee ³o­Ó®æ¦¡³Ì¤j¥u¯à³o»ò¤j¡A½Ðª`·N¤jªº¸ê®Æ®w«Ü®e©ö´N¤j©ó³o­Ó­È
end;
destructor TXLSWriter.Destroy;
begin
if fStream <> nil then
fStream.free;
inherited;
end;
procedure StreamWriteWordArray(Stream: TStream; wr: array of Word);
var
i: Integer;
begin
for i := 0 to Length(wr)-1 do
{$IFDEF CIL}
Stream.Write(wr[i]);
{$ELSE}
Stream.Write(wr[i], SizeOf(wr[i]));
{$ENDIF}
end;
procedure StreamWriteAnsiString(Stream: TStream; S: String);
{$IFDEF CIL}
var
b: TBytes;
{$ENDIF}
begin
{$IFDEF CIL}
b := BytesOf(AnsiString(S));
Stream.Write(b, Length(b));
{$ELSE}
Stream.Write(PChar(S)^, Length(S));
{$ENDIF}
end;
procedure TXLSWriter.WriteBOF;
begin
Writeword(BOF_BIFF5);
Writeword(6); // count of bytes
Writeword(0);
Writeword(DOCTYPE_XLS);
Writeword(0);
end;
procedure TXLSWriter.WriteDimension;
begin
Writeword(DIMENSIONS); // dimension OP Code
Writeword(8); // count of bytes
Writeword(0); // min cols
Writeword(maxRows); // max rows
Writeword(0); // min rowss
Writeword(maxcols); // max cols
end;
procedure TXLSWriter.CellDouble(vRow, vCol: word; aValue: double;
vAtribut: TSetOfAtribut);
//var FAtribut:array [0..2] of byte;
begin
CXlsNumber[2] := vRow;
CXlsNumber[3] := vCol;
StreamWriteWordArray(fStream, CXlsNumber);
//SetCellAtribut(vAtribut,fAtribut);
//fStream.Write(fAtribut,3);
fStream.WriteBuffer(aValue, 8);
end;
procedure TXLSWriter.CellInteger(vRow,vCol:word;aValue:Integer;vAtribut:TSetOfAtribut=[]);
var V:Integer;
begin
CXlsRk[2] := vRow;
CXlsRk[3] := vCol;
StreamWriteWordArray(fStream, CXlsRk);
V := (aValue shl 2) or 2;
fStream.WriteBuffer(V, 4);
end;
procedure TXLSWriter.CellStr(vRow, vCol: word; aValue: String;
vAtribut: TSetOfAtribut);
var slen:Word;
begin
slen := Length(aValue);
CXlsLabel[1] := 8 + slen;
CXlsLabel[2] := vRow;
CXlsLabel[3] := vCol;
//SetCellAtribut(vAtribut, CXlsLabel[4]);
CXlsLabel[5] := slen;
StreamWriteWordArray(fStream, CXlsLabel);
StreamWriteAnsiString(fStream, aValue);
end;
procedure TXLSWriter.SetCellAtribut(value:TSetOfAtribut;var FAtribut:array of byte);
var
i:integer;
begin
//reset
for i:=0 to High(FAtribut) do
FAtribut[i]:=0;
if acHidden in value then //byte 0 bit 7:
FAtribut[0] := FAtribut[0] + 128;
if acLocked in value then //byte 0 bit 6:
FAtribut[0] := FAtribut[0] + 64 ;
if acShaded in value then //byte 2 bit 7:
FAtribut[2] := FAtribut[2] + 128;
if acBottomBorder in value then //byte 2 bit 6
FAtribut[2] := FAtribut[2] + 64 ;
if acTopBorder in value then //byte 2 bit 5
FAtribut[2] := FAtribut[2] + 32;
if acRightBorder in value then //byte 2 bit 4
FAtribut[2] := FAtribut[2] + 16;
if acLeftBorder in value then //byte 2 bit 3
FAtribut[2] := FAtribut[2] + 8;
// <2002-11-17> dllee ³Ì«á 3 bit À³¥u¦³ 1 ºØ¿ï¾Ü
if acLeft in value then //byte 2 bit 1
FAtribut[2] := FAtribut[2] + 1
else if acCenter in value then //byte 2 bit 1
FAtribut[2] := FAtribut[2] + 2
else if acRight in value then //byte 2, bit 0 dan bit 1
FAtribut[2] := FAtribut[2] + 3
else if acFill in value then //byte 2, bit 0
FAtribut[2] := FAtribut[2] + 4;
end;
procedure TXLSWriter.WriteWord(w: word);
begin
fstream.Write(w,2);
end;
procedure TXLSWriter.WriteEOF;
begin
Writeword(BIFF_EOF);
Writeword(0);
end;
procedure TXLSWriter.WriteField(vRow, vCol: word; Field: TField);
begin
case field.DataType of
ftString,ftWideString,ftBoolean,ftDate,ftDateTime,ftTime:
Cellstr(vRow,vCol,field.asstring);
ftSmallint, ftInteger, ftWord, ftAutoInc, ftBytes:
CellInteger(vRow,vCol,field.AsInteger);
ftFloat, ftBCD:
CellDouble(vRow,vCol,field.AsFloat);
else
Cellstr(vRow,vCol,EmptyStr); // <2002-11-17> dllee ¨ä¥L«¬ºA¼g¤JªÅ¥Õ¦r¦ê
end;
end;
initialization
G_XLSWriterIsRuning := False;
end.