1.背景目的
当有一大批报表需要你通过水晶报表来实现其打印、导出功能时,你不得不为这些具有相似结构的报表创建一一对应模板(rpt文件)而感到烦恼,其实,对于每一个编程人员来说,内心早就有一种想法:能不能通过一个通用的报表模板来实现这些报表所需要的功能呢?下面就从这个念头入手,解决这个烦人的问题。
2.方法思路
仔细研究一下水晶报表模板rpt的文件结构,主要有以下四个方面:
一、数据源设置
二、数据字段绑定
三、特殊字段应用
四、文本对象设置
数据源的设置需要通过绑定一个DataSet文件,对于不同的报表,具有不同的报表数据结构,所以问题的关键所在就是要统一一个具有相同结构的DataSet文件,把它作为水晶报表的唯一数据源。
在具有一个统一的数据源结构之后,我们需要做到的主要有两点:
一、控制报表数据传入报表的时候我们可以将传入的DataSet数据集的表结构都转换成跟DataSet文件一样的结构(比如表名、字段名和字段数的转换);
二、在水晶报表模板中用未绑定字段和文本对报表结构进行构造。
3.创建步骤
通过上面的思路分析,我们大致已经知道了实现统一报表模板所需要做事项,下面进行具体操作:
一、准备工作
我们都知道,做每件事情必定是有得有失的,主要是得要多与失,并达到我们的理想目标,在统一报表模板的时候,我们必定会失去了每个报表的灵活显示特点,所以一开始,我们就要为这个统一的报表模板设定一个最大的字段数和实际显示数,这些都必须进行固定化,在这里,我们可以设置最大字段数MaxColumnNum=15,实际显示数为ShowColumnNum=11。
注:最大字段数大于实际显示数是为了以后的报表扩充升级做准备的。
二、创建数据集文件(rptDataSet.xsd)
创建表名为Table1表,有15个字段(与上面的最大字段数对应),字段名为rptField1、rptField2、rptField3……rptField15,全部字段的类型都设置为string。
三、创建水晶报表模板文件(rptModel.rpt)
在创建的水晶报表模板里面设置报表的数据源为rptDataSet里面的Table1。
(1)在页眉先插入一个大的文本对象,命名为rptTitle,作用是显示报表标题,然后在其下面插入11个文本对象,分别命名为rtpTitleStr1、rtpTitleStr2、rtpTitleStr3……rtpTitleStr11,作用是显示报表列标题。
(2)在详细资料里面插入11个未绑定字段,分别命名为UnboundString1、UnboundString2、UnboundString3……UnboundString11,作用是显示报表数据。
在UnboundString1上面右键,然后编辑公式如下:
WhileReadingRecords;
StringVar x1:={Table1.rptField1};
其它未绑定字段可以参照这种格式绑定其它的表字段。
四、创建报表显示文件(rptView.aspx)
在aspx文件中添加CrystalReportViewer控件CrystalReportViewer1。
双击页面打开对应的rptView.aspx.cs程序文件,然后在添加一下代码:
//实例化billsreportTest对象rptDoc
SDCenter.Report.billsreportTest rptDoc = new SDCenter.Report.billsreportTest();
//改变dsTmp(报表数据集)表结构的字段名,已rptField+1(2、3....)的形式命名
for(int i=0;i<dsTmp.Tables[0].Columns.Count;i++)
{
dsTmp.Tables[0].Columns[i].ColumnName="rptField"+(i+1);
}
//以最大字段数15为上限,为dsTmp添加缺少的字段
int ColumnsAdd=15-Convert.ToInt32(dsTmp.Tables[0].Columns.Count);
for(int k=0;k<ColumnsAdd;k++)
{
dsTmp.Tables[0].Columns.Add("rptField"+(15-k));
}
//rptDoc绑定数据源
rptDoc.SetDataSource(dsTmp);
//创建报表模板中的文本对象rptTitle,并对其进行赋值
TextObject rptTitleText=rptDoc.ReportDefinition.ReportObjects["rptTitle"] as TextObject;
rptTitleText.Text=”报表标题”;
//对报表模板格式进行初始化定义
string rptTitleStr=Session["rptTitleStr"].ToString();
string [] rptTitleArray=rptTitleStr.Split(',');
string rptShowTitleTmp=Session["rptShowTitle"].ToString();
int j=0;
for(int i=0;i<rptShowTitleTmp.Length;i++)
{
if(Convert.ToInt32(rptShowTitleTmp.Substring(i,1))>0)
j+=1;
}
if(j==0)
j=1;
int rptWidth=16410,rptLeftBegin=120;
int ColumnsShow=j;
int ColumnsNoShow=11-j;
int ColumnsWidth=Convert.ToInt32(rptWidth/j);
for(int h=0;h<11;h++)
{
//在定义报表模板内最大列为11的情况下,隐藏没有关联的列及其对应列标题
if(Convert.ToInt32(rptShowTitleTmp.Substring(h,1))==0)
{
TextObject rtpTitleStrText=rptDoc.ReportDefinition.ReportObjects["rtpTitleStr"+(h+1)] as TextObject;
rtpTitleStrText.ObjectFormat.EnableSuppress=true;
FieldObject rptDataStrText=rptDoc.ReportDefinition.ReportObjects["UnboundString"+(h+1)] as FieldObject;
rptDataStrText.ObjectFormat.EnableSuppress=true;
}
else
{
//平均报表模板显示列的宽度
try
{
TextObject rtpTitleStrText=rptDoc.ReportDefinition.ReportObjects["rtpTitleStr"+(h+1)] as TextObject;
rtpTitleStrText.Width=ColumnsWidth;
rtpTitleStrText.Left=rptLeftBegin;
rtpTitleStrText.Text=rptTitleArray[h];
FieldObject rptDataStrText=rptDoc.ReportDefinition.ReportObjects["UnboundString"+(h+1)] as FieldObject;
rptDataStrText.Width=ColumnsWidth;
rptDataStrText.Left=rptLeftBegin;
rptLeftBegin+=ColumnsWidth;
}
catch(System.Exception e1)
{
}
}
}
//CrystalReportViewer1绑定数据源
CrystalReportViewer1.ReportSource = rptDoc;
CrystalReportViewer1.DataBind();
4.不足之处与优化
一、有最大字段数与字段显示数的限制
二、可以通过传输宽度大小参数来控制报表列的显示宽度