前言
Crystal Report的功能性自不必说,虽说有时做一些比较有中国特色的报表有些困难,但是功能上应该还是挺强的。Crystal Report在VS/VS.NET中应用的文章已经很多了,RDC在VB中的效果也是相当不错,在VS.NET中甚至集成了Crystal Report,虽然不是全功能版,但是做一般的报表,应该是没有问题的,尤其在.net中做的报表,可以以WEB的方式呈现给User,也是相当不错的。但是有关在Delphi中使用Crystal Report的文章却很少,也许是Delphi中报表工具都是被QReport,FastReport,Rava,Report machine等这些工具霸占着。其实这些工具也是相当不错的,只是如果原本就对Crystal Report就比较熟悉的Delphi程序员来说,在Delphi中尝试来使用一下水晶报表也还是不错的,Business Object有发布VCL Component For CR ,虽然有些Bug,但是应该还是不错了。
使用步骤
1) 下载CrystalVCL:可以去BO的网站下载,下载网址:
http://www.businessobjects.com/products/reporting/crystalreports/vcl/download.asp。目前官方网站有提供三个版本的VCL.CR9/CR10/CR XI,不过没有比较新版本的CR XI Release 2及2008的。有一点不爽的是在下载的时候要求提供注册号,正版的用户应该没有问题,不过其他的非官方网站应该也有提供下载。CR9的VCL有相当多的Bug,需要自己去修改它的pas文件源代码。CR10未测试,以下的资料是CR XI的。比较好的一点是此VCL有提供源码,如果发现有Bug,可以自己作修改。可能是开发此控件的人delphi功力还不够,呵呵!还有一种是直接使用Crystal Report的ActiveX,不过不建议使用这种方法。
2) 安装VCL:安装VCL的过程非常简单,一般在下载的文件里面都有Readme的说明,按照步骤来做就好了。简单来说,就是首先在Delphi的library path里面增加CRVCL的路径,然后在Delphi里面打开dcl7cr11这个package(不同版本的VCL文件名称会有不同),Compile后install就可以了。安装完后,会在Data Access中产生两个控件:Crpe跟CrpeDS。Crpe封装了CR的大部分功能,CrpeDS是将Delphi的DataSet传递给Crpe来进行报表的显示,主要用于Push模式,如果是pull模式,则Crpe就足够了下面会详细说明。
3) Pull模式编程:所谓Pull模式,简单来说就是rpt文件中会自动从datasource中抓取数据,Crpe就把数据认证信息跟参数等信息传递过去就可以了。(CR可以连接大部分的数据源,这点不用担心,甚至于非传统的数据库,比如Windows server的AD信息跟Outlook的信息等)。报表要提前设计好,报表的设计方法,这里不再赘述,有兴趣的可以加我QQ交流经验。也可以参考相关的书籍或者CR的在线帮助。以下的代码供参考:
Screen.Cursor:=crHourGlass;
Crpe1.Clear;
Crpe1.ReportName:='Test.rpt';
Crpe1.Connect.ServerName:='localhost';
Crpe1.Connect.UserID:='sa';
Crpe1.Connect.Password:='sa';
Crpe1.Connect.DatabaseName:='Test';
Crpe1.Connect.Propagate:=True;
Crpe1.DiscardSavedData;
Crpe1.ProgressDialog:=True;
Crpe1.Output:=ToWindow;
Crpe1.WindowButtonBar.GroupTree:=True;
Crpe1.WindowButtonBar.ZoomCtl:=True;
Crpe1.WindowButtonBar.PrintSetupBtn:=True;
Crpe1.WindowState:=wsMaximized;
Crpe1.WindowStyle.Title:='测试水晶报表预览窗口';
Crpe1.WindowEvents:=True;
………………………………
//Crpe1.wOnExportBtnClick:=CrpewOnExportBtnClick;
Crpe1.ParamFields[0].CurrentValue:='1';
Crpe1.Execute;
Screen.Cursor:=crDefault;
4) Push模式编程:所谓Push模式,简单来说就是DataSet由前端组织,然后将Data Push给CR,而不是由CR直接连接数据库来抓取数据,此方法比较灵活,可以使用Delphi中功能丰富的dataset控件来组织、过滤数据,delphi中的dataset控件,比如Table、Query、DataSet等都是可以的,甚至于内存表也没有问题,比如ClientData,或者是第三方的内存表控件都可以,这就大大增加了报表的自由度,可以将Delphi强大的数据存取功能跟CR的功能组合起来使用。这里面有一个问题就是,没有了数据源,在设计报表的时候数据库的连接要如何选择?这里提供一个方法:你可以使用一个“仅字段定义”文件即可。文件大概类似如下的模样:
f01 String
10
f03 String
40
f40 date
f50 number
fcuser
string 10
保存为.ttx为扩展名的文本文件即可,ttx中的每一行就代表了每一个字段名称、长度、类型,此文件可以在CR的开发环境中产生,也可以自已使用notepad来制作。然后在CR的新建连接中选择“仅字段定义”即可,指定为刚才产生的文件,如果以后有修改此ttx文件,直接在CR的菜单中选在验证数据库即可添加或者删除字段。参考代码如下:
AdoQuery1.Active:=False;
AdoQuery1.SQL.Clear;
AdoQuery1.SQL.Add(Edit1.Text);
Try
AdoQuery1.Active:=True;
Except
ShowMessage('打开数据集失败,请确认输入的SQL语法是否正确!');
Exit;
end;
Screen.Cursor:=crHourGlass;
Crpe2.Clear;
Crpe2.ReportName:='Test_TTX.rpt';
Crpe2.DiscardSavedData;
Crpe2.ProgressDialog:=True;
Crpe2.Output:=ToWindow;
Crpe2.WindowButtonBar.GroupTree:=True;
Crpe2.WindowButtonBar.ZoomCtl:=True;
Crpe2.WindowButtonBar.PrintSetupBtn:=True;
Crpe2.WindowState:=wsMaximized;
Crpe2.WindowStyle.Title:='测试水晶报表预览窗口';
Crpe2.WindowEvents:=True;
//Crpe2.wOnExportBtnClick:=CrpewOnExportBtnClick;
…………………………………………….
Crpe2.Tables[0].DataPointer := CrpeDS2.DataPointer;
Crpe2.ParamFields[0].CurrentValue:='2';
Crpe2.Execute;
Screen.Cursor:=crDefault;
主要的代码就两句:
Crpe2.Tables[0].DataPointer := CrpeDS2.DataPointer;
Crpe2.Execute;
前提是CrpeDS的Dataset控件的属性要设置为你所要使用数据来源控件,此示例代码中是:AdoQuery1 。如果要使用内存表,可以参考如下的代码:
Screen.Cursor:=crHourGlass;
ClientDataSet1.Close;
With ClientDataSet1.FieldDefs do
Begin
Clear;
Add('f01',ftString,5,False);
Add('f02',ftString,40,False);
Add('f03',ftString,40,False);
Add('f04',ftString,20,False);
Add('f05',ftString,40,False);
End;
ClientDataSet1.CreateDataSet;
ClientDataset1.Open;
AdoDataSet1.First;
While not AdoDataSet1.Eof do
Begin
ClientDataSet1.Append;
ClientDataSet1.FieldByName('f01').AsString := AdoDataSet1.FieldByName('f01').AsString;
ClientDataSet1.FieldByName('f02').AsString := AdoDataSet1.FieldByName('f02').AsString;
ClientDataSet1.FieldByName('f03').AsString := AdoDataSet1.FieldByName('f03').AsString;
ClientDataSet1.FieldByName('f04').AsString := AdoDataSet1.FieldByName('f04').AsString;
ClientDataSet1.FieldByName('f05').AsString := AdoDataSet1.FieldByName('f05').AsString;
ClientDataSet1.Post;
AdoDataSet1.Next;
End;
AdoDataSet1.Close;
Crpe4.Clear;
Crpe4.ReportName:='Test_TTX.rpt';
Crpe4.DiscardSavedData;
Crpe4.ProgressDialog:=True;
Crpe4.Output:=ToWindow;
Crpe4.WindowButtonBar.GroupTree:=True;
Crpe4.WindowButtonBar.ZoomCtl:=True;
Crpe4.WindowButtonBar.PrintSetupBtn:=True;
Crpe4.WindowState:=wsMaximized;
Crpe4.WindowStyle.Title:='测试水晶报表预览窗口';
Crpe4.WindowEvents:=True;
//Crpe4.wOnExportBtnClick:=CrpewOnExportBtnClick;
………………………………………..
CrpeDS4.DataSet:=ClientDataSet1;
Crpe4.Tables[0].DataPointer := CrpeDS4.DataPointer;
Crpe4.ParamFields[0].CurrentValue:='2';
Crpe4.Execute;
Screen.Cursor:=crDefault;
内存表的数据可以来源于xml等,即可以不使用数据库引擎,在发布程序的时候比较方便,不用将数据引擎打包发布。
5) 程序分发:程序发布可以去官方网站下载合并模块Merge Modules,此模块很容易在网上找到。然后使用wise或者installshield等打包工具将此合并模块加入程序包的project中并做一些简单的设置即可,installshield等工具中甚至集成了CR的Merge Modules,直接选择对应的版本即可。
后记
以上代码是在delphi7+SQL Server+WindowsXP Professional中测试通过,水晶报表还是挺不错的报表工具,有兴趣的不妨一试。不过对于自定义纸张的报表,CR一直没有很好的解决方案,确实遗憾。