程序员手册
一.使用方法.
安装后,你可以在Delphi控件面板上看到ACReport这个控件。它提供了以下两个重要的属性:
1. DataSets :设置报表用到的所有数据集。当最终用户选取字段时,这里设置的数据集与字段都会呈现出来。
用以下方法可以动态设置或加入一个数据集:
AReport.DataSets.SetDataSet(名称,数据集),如:AReport.DataSets.SetDataSet('主表', Query1)
2.Variants :设置变量名。你可以把一些信息如:公司名称、日期、报表的条件信息等以变量的方式传入报表,以便用户使用。你可以在 BeforePrepare事件中执行如下的语句来生成一个变量或给变量赋值:
AReport.Variants.SetVariant('使用单位名称', Edit2.Text);
AReport.Variants.SetVariant('开始时间', Date());
注册全局变量
一般用户的公司名称、地址、电话等可以注册成全局变量(系统变量),这样每个报表都可以使用。
方法:
包含 AC_Var 单元,然后调用全局对象ACSysVariants的SetVariant方法,如:
uses AC_Var;
...
ACSysVariants.SetVariant('公司名称', 'xxxx有限公司');
3.几个重要的方法:
LoadFromFile 从文件中装入一个报表
LoadFromStream 从流中装入一个报表
LoadFromBlobField 从数据库中装入一个报表
SaveToFile 保存到文件
SaveToStream 保存到流
SaveToBlobField 保存到Blob类型的字段中
(注:LoadFromStream 与 SaveToStream 中参数的类型是TACStream,它继承于TStream。)
ShowDesigner 设计报表
Print 打印
preview 预览
PrintPrepared 打印已经准备好的报表(如果你自己控制准备报表可以使用这个)
PrepareReport 准备报表
PrintWithSet 在打印前弹出打印设置的对话框
使用就这么简单,如果你的功力稍够的话,你完全可以将你的应用程序中的报表系统做得更好些,最笨的办法就是在每个Form上放一个TACReport,然后进行设置。
我的做法是在软件中用一个通用的TACReport,然后其它地方通一个函数把数据集和变量及报表名称传过来,动态设置ACReport的各属性后,从数据库中装入模板进行打印(我的模板存放在数据库中,以Form的类名和报表名称作为标识)。
**************************************************************************************
二.扩充功能。
本报表采用面向对象的方法编写,扩充功能主要是从一些基类重载一些子类,再通过调用某些特定的过程注册这些类即可以完成扩充功能。
以下是可能用到的几个重要的类:
TACReport :报表类,封装了报表的所有与界面无关的操作。
TACReportCell :单元格基类,最简单的单元格的类。
TACStyle : 报表样式的基类。
TACReportLine :报表行。
TACReportCtrl :显示报表的类。
TACPgHeadFoot :页眉页脚类。
TACFunctionManger :函数库管理类
TACFormatManager :单元格样式管理类
----------------------------------------------------------------
1.扩充函数
扩充函数很简单,在你的程序中包含ACFuncManager单元:
uses ACFuncManager;
然后:
(1).编写函数
在Delphi中写好你要增加的函数,要求是所有的参数和返回值类型都申明为Variant,如以下是增加一个取右子串的函数:
function StrRight(AStr, nLen:variant) :variant;
var ts :string;
tnLen :integer;
begin
ts := AStr;
tnLen := nLen;
Result := Copy(ts, Length(ts)-tnLen+1, tnLen);
end;
(2)注册函数
单元的initialization中调用ACFunctionManager.RegisterFunction进行注册:
initialization
with ACFunctionManager do
RegisterFunction('StrRight', @StrRight,'字符串, 长度', [dtString, dtInteger],
dtString, fcString, '从字符串右面取指定长度的子串。');
end;
参数说明:
1): 在报表中的函数名称
2): 函数地址
3): 参数说明
4): 参数类型
5): 返回值类型
6): 函数类别
7): 函数说明
(3)合计函数
以上例子是一个简单函数,如果要注册合计函数,需要重载TAggrFunc基类,TAggrFunc定义如下:
TAggrFunc = class(TObject)
private
public
procedure Init; virtual;
procedure AddAggrValue(P1 :variant); virtual;
function GetAggrValue :variant; virtual;
end;
以下是一个sum函数的例子:
TSumFunc = class(TAggrFunc)
private
FSum : real;
public
procedure Init; override;
procedure AddAggrValue(P1 :variant); override;
function GetAggrValue :variant; override;
end;
{TSumFunc}
procedure TSumFunc.Init;
begin
FSum := 0;
end;
procedure TSumFunc.AddAggrValue(P1 :variant);
begin
FSum := FSum + P1;
end;
function TSumFunc.GetAggrValue :variant;
begin
result := FSum;
end;
注册方法:
SumFunc := TSumFunc.Create();
RegisterFunction('sum', SumFunc, '表名, 表达式',[dtVariant], dtFloat,fcAggr, '合计表达式的值');
有关扩充函数的代码可参考公开源码的单元ACStdFuncLib.pas。
--------------------------------------------------------------------
2.扩充单元格样式。
如果你想扩充一种新的单元格样式,只须从TACreportCell派生一个子类,然后调用TACFormatManager.RegisterCellClass你新写的子类注册即可.
(1). 派生方法,例如以下代码是一个条码类型单元格:
TACBarC = class(TACReportCell)
private
FBarCode :TACBarCode;
FCodeType : TAcBarcodeType;
FViewText, FCheckSum :boolean;
procedure SetCodeType(AValue :TAcBarCodeType);
procedure SetBoolValue(AIndex:integer; AValue :boolean);
protected
procedure Draw(ACanvas :TCanvas); override; //可能需重载的方法
procedure LoadFromStream(AStream:TACStream); override; //可能需重载的方法
procedure SaveToStream(AStream:TACStream); override; //可能需重载的方法
public
constructor Create(); override;
destructor Destroy; override;
procedure CopyCell(Cell: TACReportCell; bCopyText, bInsert, bOnlyValue: Boolean); override;
property CodeType :TAcBarCodeType read FCodeType write SetCodeType;
property ViewText :boolean index 0 read FViewText write SetBoolValue;
property CheckSum :boolean index 1 read FCheckSum write SetBoolValue;
end;
有三个方法可能需重载:
1) procedure Draw(ACanvas :TCanvas);
绘制单元格的方法。
2) procedure LoadFromStream(AStream:TACStream);
procedure SaveToStream(AStream:TACStream);
从流中装入单元格属性的方法,如果子类有自己一些属性需要保存则需要重载这两个方法。
本例中三个方法实现如下:
procedure TACBarC.LoadFromStream(AStream:TACStream);
var i:integer;
begin
inherited;
FCodeType := TACBarCodeType(AStream.IntegerIO);
FViewText := AStream.BooleanIO;
FCheckSum := AStream.BooleanIO;
end;
procedure TACBarC.SaveToStream(AStream:TACStream);
begin
inherited;
AStream.IntegerIO := integer(FCodeType);
AStream.BooleanIO := FViewText;
AStream.BooleanIO := FCheckSum;
end;
procedure TACBarC.Draw(ACanvas :TCanvas);
var ACode :string;
ATxtHeight :integer;
hTextFont, hPrevFont: HFONT;
begin
FBarCode.Typ := FCodeType;
if CellText <> '' then
ACode := inherited Value
else if rsDesign in OwnerLine.Report.States then
begin
ACode := '01234356789';
inherited Value := ACode;
end;
if ACode = '' then
Exit;
FBarCode.Text := ACode;
FBarCode.Checksum := FCheckSum;
windows.SetTextColor(ACanvas.Handle, TextColor);
hTextFont := CreateFontIndirect(LogFont);
hPrevFont := SelectObject(ACanvas.Handle, hTextFont);
ATxtHeight := ACanvas.TextHeight('1Aa汉');
.....
end;
(2).注册
首先要在你的Unit中包含ACFormat单元:
Uses ACFormat
然后在调用ACFormatManager.RegisterCellClass方法进行注册就行,例如以下是报表程序实际的注册例子:
initialization
with ACFormatManager do
begin
RegisterCellClass(TACReportCell, '常规');
RegisterCellClass(TACNumeric, '数值');
RegisterCellClass(TACDateTime, '日期/时间');
RegisterCellClass(TACRichText, 'Rich文本');
RegisterCellClass(TACPicture, '图像');
RegisterCellClass(TACBarC, '条形码');
RegisterCellClass(TAcChart, '图表对象');
with Formats[TACNumeric] do
begin
Add('0.00|12.10/总是固定两位小数点,有利于对齐。');
Add(',0.00|-1,233.03/自动分节');
Add(',0.000|23.320');
Add('#.##|23.2');
Add(',#.##|23/自动分节,最多保留2位小数');
Add(',0.##|0.32/至少保留一个整数位');
end;
with Formats[TACDateTime] do
begin
Add('YYYY-MM-DD|2003-07-18/只显示日期部分(标准格式)。');
Add('YYYY-MM-DD HH:MM:SS|2003-07-18