其他语言

位置:IT落伍者 >> 其他语言 >> 浏览文章

用Delphi实现自己的Excel报表


发布日期:2020年09月28日
 
用Delphi实现自己的Excel报表
Excel是大家都比较熟悉的表格处理软件用它来做自由报表载体其好处有

从用户角度

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

从开发者角度

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

整体思路

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

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

报表功能实现

首先新建Excel模板如下图

模板保存为templatexlt

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

下面我们来设计一个简单的模板分析类(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 := FExcelSheetObjectCells[iRow iCol];//取当前单元格对象

CellValue := CellValueValue; //取单元格内容

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

begin

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

begin

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

end;

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

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

if IsControlTag(CellValue) then

…………………

end;

遍历循环结束

执行到这里报表生成完毕

ProcessDataSetElement

ADataSet := FindDataSet(CellValue);

for j:= to ADataSetRecordCount do

begin

FExcelSheetObjectRows[FCurrentRow + j]Delete;//将当前行删除(也就是#TableBegin()#所在的行)

FExcelSheetObjectRows[FCurrentRow + j]Insert;//新增行

FExcelSheetObjectRows[FCurrentRow + j]Copy(FExcelSheetObjectRows[FCurrentRow + ]);

for i:= FBoundLeft to FBoundLeft do

begin

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

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

FExcelSheetObjectRows[FCurrentRow + j]Cell[i] := ADataSetFieldByName(fieldname)Value; //将//相应字段的值赋入单元格

end;

ADataSetNext;

end

FCurrentRow := FCurrentRow + j;

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

TXlTemplateAnalyzer类的是这样调用

begin

先将数据集变量注册

templtAnalyzerRegisterDataSet(DataSet Table);

templtAnalyzerRegisterParam(Now Date);

templtAnalyzerRegisterParam(totalQu TotalQuantity);

templtAnalyzerRegisterParam(totalPlan TotalPlan);

templtAnalyzerRegisterParam(totalPer TotalPercent);

生成报表

templtAnalyzergenerateReport;

end;

参考文档MSDN:Microsoft Developer Net

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

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

               

上一篇:Delphi开发技巧:字符串的相关判断[5]

下一篇:Delphi - 被廉价甩卖的传奇[2]