分享
 
 
 

用Delphi实现自己的Excel报表

王朝delphi·作者佚名  2006-01-30
窄屏简体版  字體: |||超大  

Excel是大家都比较熟悉的表格处理软件,用它来做自由报表载体其好处有:

l 从用户角度:

载体本身具有脚本支持,公式编辑,模板支持,格式、版式设计等诸多功能,而这些功能对于大部分用户是比较熟悉的。省去了用户培训环节;多数办公用电脑都装有Office软件,所以,其输出的报表可以被任何装有Office软件的计算机浏览;

l 从开发者角度:

可以通过OLE访问,提供了大量的编程接口,几乎所有的操作都可以用程序来控制;利用宏、VBA等技术可以很轻松地编写报表设计模块。

整体思路:

程序通过OLE获取Excel的Sheet对象。遍历每个单元格,将模板中的元素以变量、表格等替换,就生成了最终报表。其中元素种类可分为变量元素、数据集元素、数据字段元素和其它标志元素。它们都是处于单元格内的包含特殊格式的字符串,格式可以自由定义,但要保证此格式不会与正文相冲突。

如:

#ValueAA# (变量名两边加入#号,当遍历到其所在的单元格时在程序中对单元格进行相应处理)

报表功能实现:

首先新建Excel模板,如下图:

模板保存为template.xlt

现在模板有了,现在需要实现的功能就是分析此模板,将模板中的元素替换为程序中将要输出的变量或数据表。

下面我们来设计一个简单的模板分析类(TXlTemplateAnalyzer):

公有方法:

generateReport //套用模板生成最终报表。

registerDataSet //在DataSet列表中新增数据集。

registerParam //在Param列表中新增变量。

removeDataSet //在DataSet列表中删除数据集。

removeParam //在Param列表中删除变量。

SetSheetObject //设置模板的Sheet对象

私有成员变量:

FBoundLeft, FBoundRight //保存左右列边界

FDataSetList //用于维护数据集列表的私有成员。

FParamList //用于维护变量列表的的私有成员。

FExcelSheetObject //被操作模板的Sheet对象。

FCurrentRow //当前处理的行号

FCurrentCol //当前处理的列号

私有工具方法:

ProcessDataSetElement //处理数据集元素

getTemplateBoundary //获取边界索引号

parsorFieldNameFromElement //从模板元素中提取字段名

FindParam //从FParamList中查找特定Name的变量

FindDataSet //从DataSetList中查找特定Name的DataSet

IsTamplateElement //判断是否为元素

IsDataSetFieldElement //是否为数据字段元素

IsDataSetBeginElement //是否为DataSet起始元素

IsControlTag //是否为控制元素

IsParamElement //是否为变量元素

事件:

OnParamElement

OnDataSetOperationElement

OnControlElement

OnDataSetFieldElement

OnElement

写到这里大家可能已经知道我的用意了:其实这么多类成员中,但其核心就在于generateReport和ProcessDataSetElement这两个方法。

(以下代码只是描述性的脚本代码,在Delphi中不能编译)

generateReport:

------------------循环遍历单元格---------------------

FCurrentRow := iRow;

FCurrentCol := iCol;//保存当前正在处理的行列索引号

CellObj := FExcelSheetObject.Cells[iRow, iCol];//取当前单元格对象

CellValue := CellValue.Value; //取单元格内容

if IsTamplateElement(CellValue) //判断是否为模板元素

begin

if IsDataSetBeginElement(CellValue) then //判断是否为数据集开始元素

begin

ProcessDataSetElement (CellValue); //处理数据集元素

end;

if IsParamElement then(CellValue) then //判断是否为变量元素

CellObj.Value := FindParam(CellValue); //查找变量值,填到当前单元格中

if IsControlTag(CellValue) then

………………….

end;

------------------遍历循环结束---------------------

执行到这里,报表生成完毕。

ProcessDataSetElement:

ADataSet := FindDataSet(CellValue);

for j:=0 to ADataSet.RecordCount - 1 do

begin

FExcelSheetObject.Rows[FCurrentRow + j].Delete;//将当前行删除(也就是#Table.Begin()#所在的行)

FExcelSheetObject.Rows[FCurrentRow + j].Insert;//新增行

FExcelSheetObject.Rows[FCurrentRow + j].Copy(FExcelSheetObject.Rows[FCurrentRow + 1]);

for i:= FBoundLeft to FBoundLeft do

begin

fieldCellStr := FExcelSheetObject.Rows[FCurrentRow + j].Cell[i].Value; //获取数据字段元素

fieldname := parsorFieldNameFromElement(fieldCellStr); //从元素中解析字段名

FExcelSheetObject.Rows[FCurrentRow + j].Cell[i] := ADataSet.FieldByName(fieldname).Value; //将//相应字段的值赋入单元格

end;

ADataSet.Next;

end

FCurrentRow := FCurrentRow + j;

到这里,这个模板分析类的核心功能基本完成了,我想如果这个类的实现代码全部完成后,应该把这个类做成一个Component,并注册到Delphi的IDE中,以便以后使用。在上而提到的类的事件,是用来实时通知客户当前正在处理哪个Element和Cell,客户可以在此事件中做更进一步的特殊处理(例如将上述模板中产值小于完成计划数的单元格置为红色等等),非常灵活,但是出于代码整洁,在这里我没有加到代码中。另外在程序中还可以在报表中加入Excel的各种Chart、Shape等对象,这些留着我以后再写吧。

TXlTemplateAnalyzer类的是这样调用:

begin

1先将数据集、变量注册。

templtAnalyzer.RegisterDataSet(DataSet1, ‘Table);

templtAnalyzer.RegisterParam(Now, ‘Date’);

templtAnalyzer.RegisterParam(totalQu, ‘TotalQuantity’);

templtAnalyzer.RegisterParam(totalPlan, ‘TotalPlan’);

templtAnalyzer.RegisterParam(totalPer, ‘TotalPercent’);

2生成报表

templtAnalyzer.generateReport;

end;

参考文档:MSDN:Microsoft Developer Net

好了,大家不妨按我的思路试试,希望我的这篇文章能给大家带来帮助。

本人口才不好,又是初次写文档,难免会有不合适的地方,欢迎大家指正,我定会继续努力的。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有