一、环境安装
开发工具使用VS2010+SAP Crystal Reports13_0+.NETformwork4.0
因为vs2010已经不再集成水晶报表,所以需要我们去找合适的版本下载http://scn.sap.com/docs/DOC-7824
或者直接点击连接下载开发安装包(开发工具包)
http://downloads.businessobjects.com/akdlm/cr4vs2010/CRforVS_13_0.exe
直接下载部署环境安装包(MSI环境包):
32位系统:http://downloads.businessobjects.com/akdlm/cr4vs2010/CRforVS_redist_install_32bit_13_0.zip
64位系统:http://downloads.businessobjects.com/akdlm/cr4vs2010/CRforVS_redist_install_64bit_13_0.zip
系统打包需要文件(MSM集合包):
http://downloads.businessobjects.com/akdlm/cr4vs2010/CRforVS_mergemodules_13_0.zip
Install Executable: 包括VS插件、报表设计器、运行环境等所有东西,装上后就可以在VS中创建CR报表。也就是说是开发环境的安装包;
MSI 32/64 Bit: 运行环境独立安装包,分别适用于32/64平台。用于开发完成服务器部署使用;
MSM 32 Bit: 也是运行环境,只不过是用来合并在安装包中的,不能独立安装。看起来只有32位版;下文我所谓的MSM合并法就指它
“下一步”安装,成功后在左侧工具栏会发现多处三个工具。
工具 | 作用 |
CrystalReportViewer | 该控件将报表显示在基于页面的布局中,可在页面之间进行移动。 |
CrystalReportPartsViewer | 该控件将报表摘要信息显示在一个类似于门户的小窗口中,可通过一系列的链接部件向下钻取到报表。 |
CrystalReportSource | 数据源空间,绑定数据后作为CrystalReportViewer的数据源使用。 |
二、报表应用与设计
把CrystalReportViewer空间放在页面上,接下来可以为其配置数据源。
数据源的配置有两种方式,直接通过数据库连接绑定数据,另一种位灵活数据员绑定(自建实体类或者自建数据集)。
介绍一种常用的定义数据源也就是大家说的PUSH模式。
1、设计数据集
在此因为报表中涉及到绑定数据库筛选结果的多条记录,所以先创建.xsd数据集
新建文件后,点击添加工具箱DataTable,一个作为获奖记录显示,一个作为培训记录显示。
设置完成后,保存。可以在页面CS文件进行直接赋值。
2.设计报表
报表头部和尾部在报表中制作一次显示。
打开数据专家,建立数据连接。
在报表中绑定数据字段
这个地方值得注意的是,在设计好详细资料的数据,如果详细资料的空白位置拉的太长会将下一条数据显示至至空白后,入股页面过小将会造成只办电影出一条数据。
对于实际需求,在本报表中出了头部信息和上面的培训信息外还需要获奖信息,这些都是一句个人的情况去绑定,所以这时需要添加子报表来完成数据的绑定。
插入子报表,以相同的模式编辑自报表,为了显示数据的美观,我们可以把页眉和页脚设置为“抑制显示(无向下钻去)”,也就是说不在界面中显示他们。
子报表是可以在主报表添加新栏进行编辑的。
因为报表中出现了盖章等信息,可以通过‘节专家’添加报表尾abc或更多。
3、数据绑定
string path = Server.MapPath("~/ReportForm/CrystalReport.rpt"); ReportDocument myReport = new ReportDocument(); myReport.Load(path); //为包含子报表和主报表指定数据源,这部分数据可重叠在(详细资料)绑定 DataSet1 DSourse = new DataSet1(); //获取培训记录 DataTable DtTRecord = new Facade_PX.Info.InfoQuery().Query_Px_Ercp_People_Train_Record(strCondtion); if (DtTRecord != null && DtTRecord.Rows.Count > 0) { for (int tr = 0; tr < DtTRecord.Rows.Count; tr++) { DataRow TRdr = DSourse.PX_ERCP_PEOPLE_TRAIN_RECORD.NewRow(); TRdr["HOSPITAL_NAME"] = "医院名称"; TRdr["TRAIN_HOSPITAL"] = DtTRecord.Rows[tr]["TRAIN_HOSPITAL"]; TRdr["DURATION_NAME"] = "培训时间"; TRdr["TRAIN_DURATION"] = DtTRecord.Rows[tr]["TRAIN_DURATION"]; DSourse.PX_ERCP_PEOPLE_TRAIN_RECORD.Rows.Add(TRdr); } } //绑定获奖记录 DataTable DtTAwards = new Facade_PX.Info.InfoQuery().Query_Px_Ercp_People_Awards(strCondtion); if (DtTAwards != null && DtTAwards.Rows.Count > 0) { for (int aw = 0; aw < DtTAwards.Rows.Count; aw++) { DataRow AWdr = DSourse.PX_ERCP_PEOPLE_AWARDS.NewRow(); AWdr["AWARDS_NAME"] = "获奖经历"; AWdr["AWARDS_RECORD"] = DtTAwards.Rows[aw]["AWARDS_RECORD"]; DSourse.PX_ERCP_PEOPLE_AWARDS.Rows.Add(AWdr); } } myReport.SetDataSource(DSourse); //为RTF报表指定静态文本
((TextObject)myReport.ReportDefinition.ReportObjects["Title"]).Text = "中国ERCP技术标准化人才培训项目申请表"; //用实体类的数据填充表格中出现字段
((TextObject)myReport.ReportDefinition.ReportObjects["ApplyName"]).Text = Info.Apply_name; //隐藏工具栏 CrystalReportViewer1.DisplayToolbar = false;
//隐藏菜单栏工具
CrystalReportViewer1.HasToggleGroupTreeButton = false;
CrystalReportViewer1.DisplayGroupTree = false;
CrystalReportViewer1.HasCrystalLogo = false;
CrystalReportViewer1.HasGotoPageButton = false;
CrystalReportViewer1.HasPageNavigationButtons = true;
CrystalReportViewer1.HasSearchButton = false;
CrystalReportViewer1.HasZoomFactorList = false;
CrystalReportViewer1.HasRefreshButton = false; //指定数据源 CrystalReportViewer1.ReportSource = myReport;
数据绑定,开始预览时,往往程序会出现无效数据员等异常。解决办法:首先检查绑定数据对象是否存在,通过调试检查是否有代码上的问题。如果代码没问题那么就要检查类库的引用是否为同一个版本,如果不是则修改版本为最新版本。修改版本一致,主要修改几项如下:
页面修改:
<%@ Register Assembly="CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304" Namespace="CrystalDecisions.Web" TagPrefix="CR" %>
Webconfig修改:
<system.web> <compilation debug="true" targetFramework="4.0"> <assemblies> <add assembly="CrystalDecisions.CrystalReports.Engine, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/> <add assembly="CrystalDecisions.ReportSource, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/> <add assembly="CrystalDecisions.Shared, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/> <add assembly="CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/> <add assembly="CrystalDecisions.ReportAppServer.ClientDoc, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/> </assemblies> <buildProviders> <add extension=".rpt" type="CrystalDecisions.Web.Compilation.RptBuildProvider, CrystalDecisions.Web, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/> </buildProviders> </compilation> </system.web>
预览结果:
三、报表打印与部署
1.报表打印
获取当前默认打印机
/// <summary> /// 打印机实例 /// </summary> private static PrintDocument fPrintDocument = new PrintDocument(); /// /// 获取本机默认打印机名称 /// public static String DefaultPrinter { get { return fPrintDocument.PrinterSettings.PrinterName; } }
打印数据
myReport.PrintOptions.PrinterName = DefaultPrinter; myReport.PrintToPrinter(1, false, 0, 0);
2.服务器部署
服务器部署正确配置也比较简单
下载在第一部分提到的环境32位和64位环境包,如果是在32环境下开发,并且已经在应用程序池Enable 32-Bit Applications 为True。那么一定要安装32位CRforVS_redist_install_32bit_13_0.zip否则会出现<add assembly="CrystalDecisions.ReportAppServer.ClientDoc, Version=13.0.2000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>的引用错误。
调试通过后,点击打印预览会发现报表一片空白,这时因为还未将皮肤引用文件引用到IIS的WebSite,需要将C:\inetpub\wwwroot\aspnet_client此路径下的文件拷贝到站点的根目录,浏览即可。
值得注意的是在服务器,由于PrintDocument获取的是服务器打印机所以会出现“默认打印机未设置”的错误提示,所以这里我们就使用水晶报表工具栏自带打印按钮。
首选,先将CrystalReportViewer1设置为PrintMode="ActiveX",再将工具栏的打印按钮显示出来CrystalReportViewer1.HasPrintButton = true。
在你弹出打印预览的Click事件中使用Session记录ReportDocument
代码如下:Session["keepreport"] = myReport;
在页面加载Page_Load中加入
if (Session["keepreport"] != null) { CrystalReportViewer1.ReportSource = (ReportDocument)Session["keepreport"]; }
主要是因为页面刷新的问题。
3.异常处理
用着用着,一段时间后会发现出现异常“已达到系统管理员配置的最大报表处理作业数限制”,
在这篇博客中也有讲到如何解决
水晶报表服务器运行一段时间提示错误:已达到系统管理员配置的最大报表处理作业数限制。
但正因为这个原因导致,后期打印按钮不能打印。
经过对页面生命周期分析后,将ReportDocument资源释放放在Page_Disposed中即可完美解决,不能打印问题。
Page_Unload:页面从内存中卸载
Page_Disposed:Page对象从内存中释放掉。这是Page对象生命周期中的最后一个事件
所以明显就可以对比处结果。