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
好了,大家不妨按我的思路試試,希望我的這篇文章能給大家帶來幫助。
本人口才不好,又是初次寫文檔,難免會有不合適的地方,歡迎大家指正,我定會繼續努力的。
|