在没有安装EXCEL的机器上,导出XLS的最佳方案。解决思路

在没有安装EXCEL的机器上,导出XLS的最佳方案。
因为客户的机器不一定安装EXCEL,也不能要求客户一定要安装EXCEL,所以需要此解决方案
这个问题,有谁做过研究吗?
有哪些方案
哪种方案最好?

------解决方案--------------------
直接用流写盘,Excel的每个单元格是有格式,格式如下:

XlsBof : array[0..5] of Word = ($809, 8, 0, $10, 0, 0);
XlsEof : array[0..1] of Word = ($0A, 00);
XlsLabel : array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
XlsNumber: array[0..4] of Word = ($203, 14, 0, 0, 0);
XlsRk : array[0..4] Of Word = ($27E, 10, 0, 0, 0);
XlsBlank : array[0..4] of Word = ($201, 6, 0, 0, $17);


------解决方案--------------------
以下是自己以前封装的一个vcl,可给给你参考。

{ 记录集数据导出到组件 TLynDataSetToExcel V1.0 版本 }
{来源:该组件设计思想来自王寒松 CReport 中文报表组件,即直接用流写xls格式文件 }
{特点:该组件直接按照Excel各Cell格式用流的形式写Excel文件,所以无需安装Excel服务}

{-------------- by 天行者 lynmison@126.com @2005.12.27 ------------------------}
 
unit LynDataToXls;

interface

uses
SysUtils, Classes, DB;

type
{表字段字典}
TLynField=record
id : integer; {序号}
name : string; {字段名称}
sName : string; {显示名称}
width : integer; {宽度}
end;
{字段列表--------------------------------}
TLynFieldList=record
nField: integer;
fields: array of TLynField;
end;

type
TLynDataSetToExcel = Class(TComponent)
private
FMax: Word;
FCol: Word;
FRow: Word;
FFields: TLynFieldList;
FHeader: TStrings;
FFooter: TStrings;
FCaption: String;
FDataSet: TDataSet;
FStream: TStream;
FBookMark: TBookmark;

procedure SetHeader(Value: TStrings);
procedure SetFooter(Value: TStrings);

procedure IncColRow(NewRow: Boolean=FALSE);
procedure WriteBlankCell(NewRow: Boolean=FALSE);
procedure WriteFloatCell(const AValue: Double; NewRow: Boolean=FALSE);
procedure WriteIntegerCell(const AValue: Integer; NewRow: Boolean=FALSE);
procedure WriteStringCell(const AValue: String; NewRow: Boolean=FALSE);
procedure WritePrefix;
procedure WriteSuffix;
procedure WriteHeader;
procedure WriteColumnHead();
procedure WriteCaption;
procedure WriteFooter;
procedure WriteDataCell;

procedure CalcMaxColumn();
procedure SaveExcelStream(Stream: TStream);
public
procedure SaveExcelFile(FileName: String);
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Fields : TLynFieldList read FFields write FFields;
property Header : TStrings read FHeader write SetHeader;
property Footer : TStrings read FFooter write SetFooter;
property Caption: String read FCaption write FCaption;
property DataSet: TDataSet read FDataSet write FDataSet;
end;

procedure Register;

implementation

var
XlsBof : array[0..5] of Word = ($809, 8, 0, $10, 0, 0);
XlsEof : array[0..1] of Word = ($0A, 00);
XlsLabel : array[0..5] of Word = ($204, 0, 0, 0, 0, 0);
XlsNumber: array[0..4] of Word = ($203, 14, 0, 0, 0);
XlsRk : array[0..4] Of Word = ($27E, 10, 0, 0, 0);
XlsBlank : array[0..4] of Word = ($201, 6, 0, 0, $17);

procedure TLynDataSetToExcel.SetHeader(Value: TStrings);
begin
if Value=nil then FHeader.Clear
else FHeader.Assign(Value);
end;

procedure TLynDataSetToExcel.SetFooter(Value: TStrings);
begin
if Value=nil then FFooter.Clear
else FFooter.Assign(Value);
end;

constructor TLynDataSetToExcel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FDataSet := nil;
FHeader := TStringList.Create;
FFooter := TStringList.Create;