您的位置:首页 > 其它

随笔『使用ActiveReport for .net 进行报表开发』

2008-01-19 16:23 369 查看
[align=left](一)--开始 [/align]
[align=left]ActiveReport 是.net下的一个出色的报表开发程序,虽然和水晶报表相比,名气不那么大,甚至有很多人不知道它的存在,但是并不妨碍它在.net报表开发中的出色表现,本文将一步一步地介绍如何使用它和VS2005开发.net报表。[/align]
[align=left] [/align]
[align=left]1. 安装:[/align]
[align=left]你可以从Data Dynamics的网站上下载最新的ActiveReport for .net 2 ,你可以免费使用,但是在生成的报表最下边有水印,不过不影响报表的整体美观。下载后直接安装就可以了。安装完后会看到开始-程序菜单里的DataDynamics的目录,里面包括了,帮助,例子程序等。[/align]
[align=left]2. 第一个Winform报表程序。[/align]
[align=left]在安装完成后,启动VS2005,会看到启动界面上有ActiveReport的图标,进入后新建一个工程,并且给工程添加新文件,在文件类型中就可以看到ActiveReport文件的图标。给报表文件命名为ActiveReport1,确定后会看到项目中有一个ActiveReport1.rpx文件,这个就是报表文件了。[/align]
[align=left]打开文件,就是报表的设计界面,在这里可以看到三部分,PageHeader(表头),Detail(明细),PageFooter(表尾)。打开工具箱,给Detail部分随便添加一个Label。[/align]
[align=left]下面就要显示这个报表了,在Form上添加一个Viewer控件,如果工具箱里没有,可以通过配置工具箱来找到它。Viewer添加完后,在Form中写代码:[/align]
[align=left]ActiveReports1 rpt = new ActiveReports1();[/align]
[align=left] rpt.Run();[/align]
[align=left] this.viewer1.Document = rpt.Document;[/align]
[align=left]然后F5运行,就可以看到在Viewer控件中显示报表了。[/align]
[align=left]要注意的是,项目名称不要命名为ActiveReport,否则会提示找不到ActiveReport.rpx文件。[/align]
[align=left]3. 第一个web报表程序。[/align]
[align=left]Web方式的报表开发方式和winform的差不多,不同的是,web方式下需要作一些配置,配置过程不再累述,可以在帮助里搜索“Manually Configuring Web Samples”,按照里面的步骤对IIS作配置。[/align]
[align=left]要注意的是,如果使用的是VS2005,那么可以不作配置,只要在创建Web项目的时候文件位置选项设置为“文件系统”就可以直接运行了。还要注意的是,在web方式下,需要在web.config文件中添加下面这段:[/align]
[align=left]<httpHandlers>[/align]
[align=left]<addverb="*"path="*.rpx"type="DataDynamics.ActiveReports.Web.Handlers.RpxHandler, ActiveReports.Web, Version=4.2.1.1238, Culture=neutral, PublicKeyToken=cc4967777c49a3ff"/>[/align]
[align=left]<addverb="*"path="*.ActiveReport"type="DataDynamics.ActiveReports.Web.Handlers.CompiledReportHandler, ActiveReports.Web, Version=4.2.1.1238, Culture=neutral, PublicKeyToken=cc4967777c49a3ff"/>[/align]
[align=left]<addverb="*"path="*.ArCacheItem"type="DataDynamics.ActiveReports.Web.Handlers.WebCacheAccessHandler, ActiveReports.Web, Version=4.2.1.1238, Culture=neutral, PublicKeyToken=cc4967777c49a3ff"/>[/align]
[align=left]</httpHandlers>[/align]
[align=left]如果是VS2005,系统会自动添加。[/align]
[align=left]接下来的就和winform下的差不多了,不同的是,要在解决方案中新增一个“类库”项目,在这个项目中新建报表文件,然后在Web项目中添加对类库项目的引用,然后在页面上添加WebViewer控件,然后编写代码:[/align]
[align=left]this.WebViewer1.Report = new YourNamespace.ActiveReports1();[/align]
[align=left]然后运行界面,就可以看到在WebViewer中加载的报表了。[/align]
[align=left]你可以通过WebViewer的ViewType属性来设置在页面上如何显示,例如,如果选择了AcrobatReader,就会给报表生成一个PDF文档在页面上嵌入显示。

下次我们将演示如何在报表上加载和显示数据[/align]

[align=left](二)--绑定数据源 [/align]
[align=left]在上篇随笔中写了一个使用ActiveReport for .net 的最简单的例子,本文将演示在ActiveReport中如何绑定数据源[/align]
[align=left] [/align]
[align=left]1. 先建一个表chartingTable,有两个字段,OnlineUserCount,Project,通过向导生成DataSet,并拖放生成TableAdapter。[/align]
[align=left]2. 接下来在报表设计器中设计显示格式,在PageHeader中放置两个label,分别为“项目”和“在线人数”。再在Detail区方式两个对应的Label,分别设置DataFiled为Project和OnlineUserCount,在运行的时候将会看到这两个Label显示的是对应字段中的内容。[/align]
[align=left]3. 可以给报表指定DataSet或DataView作为数据源,下面演示给报表设置数据源:[/align]
[align=left]使用DataSet:[/align]
[align=left]this.chartingTableTableAdapter.Fill(this.dataSet1.ChartingTable);[/align]
[align=left]rpt.DataSource = this.dataSet1;[/align]
[align=left]rpt.DataMember = this.dataSet1.ChartingTable.TableName;[/align]
[align=left]rpt.Run();[/align]
[align=left]this.viewer1.Document = rpt.Document;[/align]
[align=left]使用DataView:[/align]
[align=left]this.chartingTableTableAdapter.Fill(this.dataSet1.ChartingTable);[/align]
[align=left]DataView dv = this.dataSet1.ChartingTable.DefaultView; ;[/align]
[align=left]rpt.DataSource = dv;[/align]
[align=left]dv.RowFilter = "project ='1'";[/align]
[align=left]rpt.Run();[/align]
[align=left]this.viewer1.Document = rpt.Document;[/align]
[align=left]4. 我们还可以通过报表设计器来给报表指定数据源。[/align]
[align=left]在报表设计器的Detail部分的头部,有一个数据库一样的小图标,点击它后会出现向导,按照向导一步步连接数据库,并定义查询就可以了。[/align]
[align=left] [/align]
[align=left]上面演示的是使用数据集作为数据源进行绑定,但是实际项目中经常会用到使用对象集合作为数据源显示,下一次我们将演示如何在报表上显示一个对象集合中的数据。[/align]
[align=left] [/align]

[align=left](三)--显示对象集合中的数据 [/align]
[align=left]将通过一些示例代码继续演示如何绑定对象集合以及如何从对象集合或列表中提取数据。[/align]
[align=left]1. 直接绑定:[/align]
[align=left]我们可以自己定义一个Collection,从IList继承,并使其中的每个对象都是一个实体,例如:[/align]
[align=left]Customer和CustomerCollection。然后给ActiveReport报表的DataSource直接赋值为CustomerCollection的实例就可以了。这种绑定方法在ActiveReport for .net自带的例子里有完整的演示。[/align]
[align=left]2. 手工加载显示对象的数据:[/align]
[align=left]在这里要用到两个事件:DataInitialize和FetchData。[/align]
[align=left]DataInitialize用来定义字段列表,获取数据等工作,FetchData用来指定每个字段的值。[/align]
[align=left]我们简单定义一个Customer类[/align]
[align=left]public class Customer[/align]
[align=left] {[/align]
[align=left] public int ID;[/align]
[align=left] public string Name;[/align]
[align=left] public string Address;[/align]
[align=left] }[/align]
[align=left]再给报表定义一个Customer数组,用来保存要显示的数据,比如:[/align]
[align=left]public Customer[] customers;[/align]
[align=left]还需要一个值来保存当前记录的索引:private int index =0;[/align]
[align=left]接下来在DataInitialize中定义报表有那些字段:[/align]
[align=left]this.Fields.Add("Name");[/align]
[align=left] this.Fields.Add("Address");[/align]
[align=left]然后在FetchData事件中添加以下代码:[/align]
[align=left]if (this.index >= this.customers.Length )[/align]
[align=left] {[/align]
[align=left] eArgs.EOF = true;[/align]
[align=left] return;[/align]
[align=left] }[/align]
[align=left] else[/align]
[align=left] {[/align]
[align=left] eArgs.EOF = false;[/align]
[align=left] }[/align]
[align=left] this.Fields["Name"].Value = customers[this.index].Name;[/align]
[align=left] this.Fields["Address"].Value = customers[this.index].Address;[/align]
[align=left] this.index += 1;[/align]
[align=left]这段代码的含义就是将Customer数组中的每个Customer实例的Name和Address属性值赋给报表的Name和Address字段。[/align]
[align=left]代码中的第一个if分支是判断是否已经加载到了最后一条数据,如果是,设置eArgs.EOF为ture,并返回,否则继续加载下一条数据。[/align]
[align=left]然后我们可以将要显示的数据放在Customers数组中,并启动显示报表:[/align]
[align=left]Customer[] customers = new Customer[2];[/align]
[align=left] Customer c = new Customer();[/align]
[align=left] c.Name = "James";[/align]
[align=left] c.Address = "Noljadfallsjf";[/align]
[align=left] Customer c2 = new Customer();[/align]
[align=left] c2.Name = "Joe";[/align]
[align=left] c2.Address = "adfaafadf";[/align]
[align=left] customers[0] = c;[/align]
[align=left] customers[1] = c2;[/align]
[align=left] [/align]
[align=left] rpt.customers = customers;[/align]
[align=left] rpt.Run();[/align]
[align=left] this.viewer1.Document = rpt.Document;[/align]
[align=left] [/align]
[align=left]通过上面的示例可以看到,第二种方式虽然比较烦琐,需要程序员自己处理很多东西,但是这样程序员拥有完全的操控能力,特别是需要对取出的数据作很多复杂的处理时,这样的操控能力是非常重要的。[/align]
[align=left] [/align]
[align=left]在下一篇随笔中,将展示如何使用子报表来作显示主从表。[/align]

[align=left] [/align]
[align=left](四)—显示主从表 [/align]
[align=left]上篇随笔演示了在ActiveReport for .net中如何从对象集合中提取数据。本文简单介绍如何使用子报表来显示主从表中的数据。[/align]
[align=left] [/align]
[align=left]1. 在需要显示主从表中的数据时,使用子报表能够提供很大的灵活性,一般就是把主表的信息显示在detail中,如果要每页的上方都要显示主表,就可以放在PageHeader中。再把子表的信息放在Detail中,然后把子报表中的控件直接绑定到数据源上或者使用上篇随笔中的提到的方式从对象集合中提取数据。[/align]
[align=left]2. 使用子报表:[/align]
[align=left]新建报表,然后在工具箱上可以看到SubReport控件,拖放一个控件到Detail部分,用此控件来加载子报表。[/align]
[align=left]再新建一个报表,命名为SubReport1 ,接下来在主报表中写代码,在页面设计器上选中Detail部分,在属性窗口切换到事件栏,双击Format,将会产生Detail_Format事件,下面就要在这个事件里指定子报表控件所要加载的报表。[/align]
[align=left]3. 由于Detail部分会进行重复显示的,所以,只能指定一次报表源,在这里,我们按照下面的例子:[/align]
[align=left]ActiveReport sub = null;[/align]
[align=left]private void Detail_Format(object sender, System.EventArgs eArgs)[/align]
[align=left]{[/align]
[align=left] if ( sub == null )[/align]
[align=left] {[/align]
[align=left] sub = new ActiveReports2();[/align]
[align=left] this.SubReport.Report = sub; [/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]先定义一个全局的子报表,然后在Detail_Format事件中对其进行初始化。[/align]
[align=left]4. 还有要注意的一点是,在使用完子报表后要将其释放,销毁掉,具体的代码放在主报表的ReportEnd事件中,例如:[/align]
[align=left]private void ActiveReports1_ReportEnd(object sender, System.EventArgs eArgs)[/align]
[align=left]{[/align]
[align=left] sub.Document.Dispose();[/align]
[align=left]sub.Dispose();[/align]
[align=left]sub = null;[/align]
[align=left]}[/align]
[align=left]5. 下面剩下的工作就是摆放控件并设置显示的字段了,加载数据等等了,前面的随笔都有介绍。[/align]
[align=left] [/align]
[align=left]下篇随笔中将介绍如何使用ActiveReport for .net开发交叉报表。[/align]

[align=left] [/align]
[align=left](五)—交叉报表 [/align]
[align=left]交叉报表是一种常见的报表类型,而且开发起来也是比较烦琐的一种报表,在ActiveReport中,对交叉报表提供了足够的灵活性,使你能够应对各种复杂的业务逻辑。在上篇随笔演示了显示主从表后,本篇随笔简单介绍如何制作交叉报表。[/align]
[align=left]交叉报表的一个常见应用就是用作显示销售额的报表上,例如,显示多个连锁店一年内每个月的销售额,常把月份作为列来显示,每个店用一行来表示:[/align]
[align=left]店名 1月 2月 3月 4月 …………… [/align]
[align=left]AC 500 200 10000 50000 ……………[/align]
[align=left]BC 511 85245 4545 124578 ……………[/align]
[align=left]但是在数据库中的存储常常采用下面的方式[/align]
[align=left]Sales Month Shop[/align]
[align=left]12312 1 AB[/align]
[align=left]243423 2 AB[/align]
[align=left]323232 3 AB[/align]
[align=left]1231312 1 BC[/align]
[align=left]1232 2 BC[/align]
[align=left]这样就需要在显示前对数据进行处理,把销售额和月份转换到列上,我们可以在取数据时使用sql来进行这些操作,在这里,为了演示在activeReport中的使用,把转换放到报表里来作,为了简化例子,我们只显示第一个季度每月的销售额。[/align]
[align=left]1. 取数据:[/align]
[align=left]使用Select Sales,Month,Shop from CrossReport Order by Shop这样的sql直接取数据,不作任何合计或转换处理。[/align]
[align=left]2. 转换:[/align]
[align=left]我们来定义一个简单的对象来表示最终要显示的记录:[/align]
[align=left]public class Sale[/align]
[align=left]{[/align]
[align=left] public decimal money1; //一月[/align]
[align=left] public decimal money2; //二月[/align]
[align=left] public decimal money3; //三月[/align]
[align=left] public string shopname;[/align]
[align=left]}[/align]
[align=left]同时在定义一个Sale的集合sales,来保存转换后的数据。[/align]
[align=left]由于在表中每个店会对应多条记录,为了把多条记录合并为一条,要进行下面的转换动作:[/align]
[align=left]//用来保存已经计算过的店铺,保证每个店铺只有一条记录[/align]
[align=left]ArrayList shopname = new ArrayList();[/align]
[align=left]while (dr.Read())[/align]
[align=left]{[/align]
[align=left] if (!shopname.Contains(dr.GetString(2))) //该店铺的第一条记录[/align]
[align=left] {[/align]
[align=left] Sale s = new Sale ();[/align]
[align=left] s.shopname = dr.GetString(2); //取店名 shopname.Add(s.shopname);[/align]
[align=left] if (dr.GetInt32(1) == 1) //一月[/align]
[align=left] {[/align]
[align=left] s.money1 = dr.GetDecimal(0);[/align]
[align=left]}[/align]
[align=left] else if (dr.GetInt32(1) == 2) //二月[/align]
[align=left] {[/align]
[align=left] s.money2 = dr.GetDecimal(0);[/align]
[align=left] }[/align]
[align=left] else if (dr.GetInt32(1) == 3) //三月[/align]
[align=left] {[/align]
[align=left] s.money3 = dr.GetDecimal(0);[/align]
[align=left] }[/align]
[align=left] sales.Add(s);[/align]
[align=left] }[/align]
[align=left] else //不是该店铺的第一条记录[/align]
[align=left] {[/align]
[align=left] Sale s = (Sale)sale [sales.Count - 1];[/align]
[align=left] if (dr.GetInt32(1) == 1)[/align]
[align=left] {[/align]
[align=left] s.money1 = dr.GetDecimal(0);[/align]
[align=left]}[/align]
[align=left] else if (dr.GetInt32(1) == 2)[/align]
[align=left] {[/align]
[align=left] s.money2 = dr.GetDecimal(0);[/align]
[align=left] }[/align]
[align=left] else if (dr.GetInt32(1) == 3)[/align]
[align=left] {[/align]
[align=left] s.money3 = dr.GetDecimal(0);[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left]}[/align]
[align=left]3. 表示:[/align]
[align=left]上面是对从数据库中取出的记录作转换,将其变成在报表上要显示的格式。接下来就要在报表上显示Sales集合中的数据了。我们可以按照前几篇随笔中介绍的方法来作:[/align]
[align=left]n 在界面上摆放控件,并设置其FiledName字段[/align]
[align=left]n 在报表的DataInitialize事件中设置Filed集合,取出数据:[/align]
[align=left]this.Fields.Add("money1");[/align]
[align=left] this.Fields.Add("money2");[/align]
[align=left] this.Fields.Add("money3");[/align]
[align=left] this.Fields.Add("shopname");[/align]
[align=left]this.GetReportData(); //取数据并作转换[/align]
[align=left]n 设置一个标记来表示是否显示到了最后一条记录:[/align]
[align=left]int index = 0;[/align]
[align=left]n 在FetchData事件中显示Sales集合中的数据:[/align]
[align=left]if (index == sales.Count ) //如果到了最后一条记录,就跳出[/align]
[align=left] {[/align]
[align=left] eArgs.EOF = true;[/align]
[align=left] return;[/align]
[align=left] }[/align]
[align=left] else[/align]
[align=left] {[/align]
[align=left] eArgs.EOF = false;[/align]
[align=left] }[/align]
[align=left] Sale s = (Sale)sales[index];[/align]
[align=left] this.Fields["shopname"].Value = s.shopname;[/align]
[align=left] this.Fields["money1"].Value = s.money1;[/align]
[align=left] this.Fields["money2"].Value = s.money2;[/align]
[align=left] this.Fields["money3"].Value = s.money3;[/align]
[align=left]index+=1;[/align]
[align=left]按照上面的步骤,主要的代码都完成了,当然要在窗体上显示,还要加一个Viewer,然后指定加载的报表:[/align]
[align=left]ActiveReports1 rpt = new ActiveReports1();[/align]
[align=left]rpt.Run();[/align]
[align=left]this.viewer1.Document = rpt.Document;[/align]
[align=left]如果你不满意显示的效果,可以给报表加上线框,让其显示成表格。[/align]
[align=left]总结:[/align]
[align=left]例子中的代码有重复,但是为了说明转换的过程,没有作优化,另外,也可以看到,代码中使用了ArrayList,出现了装箱,拆箱的动作,所以性能还有优化的空间。[/align]
[align=left]从表数据到显示用数据的转换可以在Sql中作,但是业务逻辑较复杂的时候,Sql就显得力不从心,例如,显示每月的数据,而且还有收入,支出,如果再加上税收,折扣,损耗,租金,和上年同期的比较等等无法预测的业务逻辑,如果把SQL写在代码中,调试成问题,如果写成存储过程,有破坏了封装。所以相比之下,在代码中进行的转换工作虽然较复杂,但是还是具有灵活的优势的。[/align]
[align=left] [/align]
[align=left] [/align]
[align=left](六)--导出报表 [/align]
[align=left]ActiveReport提供了多种文件格式的导出,包括:Html,Pdf,Text,Rtf,Xls,Tiff,这几种格式中,Pdf是效果最好,因为有了抗锯齿,线条和字体看起来都光滑的多,而且是完全的所见即所得,加上很多Web项目都采用Pdf作为报表显示的文件格式,导出Pdf应该是首选。由于是把报表直接生成了图片,Tiff格式的导出也是所见即所得的。[/align]
[align=left] [/align]
[align=left]其他的文件格式的限制都比较多,每种文件格式的限制可以在ActiveReport的帮助中搜索“Limitations in Export Formats”,其中有详细的列表。[/align]
[align=left] [/align]
[align=left]将报表导出的步骤也很简单,先要在工具栏上添加导出要用的控件,这组控件有:HtmlExport,PdfExport,RtfExport,TextExport,TiffExport,XlsExport六种。这里以PdfExport为例:[/align]
[align=left]拖放一个PdfExport控件到窗体上,就可以进行导出操作了,代码很简单,我们假设有一个报表文件和一个Viewer:[/align]
[align=left]窗体加载的时候:[/align]
[align=left]ActiveReports1 rpt = new ActiveReports1();[/align]
[align=left]rpt.Run();[/align]
[align=left]this.viewer1.Document = rpt.Document;[/align]
[align=left]在一个Button的Click中:[/align]
[align=left]this.pdfExport1.Export(this.viewer1.Document,@"z:/123.pdf");[/align]
[align=left]很简单吧,其他格式的导出也一样,例如Excel格式:[/align]
[align=left]this.xlsExport1.Export(this.viewer1.Document, @"z:/123.xls");[/align]
[align=left] [/align]
[align=left]在生成Pdf的时候要注意,有时页面设置不当,控件的大小可能会超出范围,导致报表有一部分无法打印出来,在使用AcrobatReader预览的时候,要在Print窗口,通过调整Page Scaling为None,看看右边Preview部分,有没有发生超出打印范围的情况。另外在作表格的时候要放大后看,因为经常会出现线条没有对齐或完全连接的情况,在预览的时候看不出来,但是在打印后会看到线条错位等情况。[/align]

[align=left](七)--事件 [/align]
[align=left]上篇随笔介绍了在ActievReport中导出报表,本篇随笔简单介绍ActiveReport中的重要事件。[/align]
[align=left] [/align]
[align=left]1. 只触发一次的事件:[/align]
[align=left]ReportStart在报表启动时触发。该事件在DataInitialize之前,在这里可以整个报表都要用到的对象或变量作初始化,也可以设置子报表。[/align]
[align=left]DataInitialize:这个事件在前面的几篇随笔中经常出现,经常在这里取数据,绑定数据源,设置报表的Fileds属性等。[/align]
[align=left]ReportEnd 在报表加载完成后触发。[/align]
[align=left]2. 多次触发的事件:[/align]
[align=left]FetchData在处理每一条数据时都会触发,如果是采用绑定数据源的方式,就不需要再作对Fields中每个Field的Value赋值。如果是从自定义的对象集合中提取数据,就要在这里给Fields赋值。而且,使用自定义集合的时候要自己设置事件的eArgs参数的EOF属性,该属性用来判断是否显示到了最后一条记录,如果是,就设置为true,并且直接返回。具体的代码可以参看以前的随笔。[/align]
[align=left]PageStart在报表的每页生成的时候触发,在这里作针对每个页的处理,最常见的就是显示页码。[/align]
[align=left]PageEnd在报表的每也生成完成的时候触发。[/align]
[align=left]3. 区域的事件:[/align]
[align=left]每个区域(PageHeader,Detail ,PageFooter)都有Format,BeforePrint和AfterPrint事件。最好不要在这几个事件中操作报表的Fields集合,而应该在DataInitialize和FetchData中进行。[/align]
[align=left]Format 在数据加载并绑定后触发,只有在这里才可以设置某个区域的高度。[/align]
[align=left]BeforePrint在区域被生成前触发,在这里如果设置区域的高度是不会有效果的,而且不要在这里操作数据源。[/align]
[align=left]AfterPrint在区域已经被生成并描画出后发生,可以在该事件里直接在画布上进行描画操作。[/align]
[align=left] [/align]
[align=left] [/align]
[align=left](八)--显示合计 [/align]
[align=left]在报表开发中我们常常要显示合计,比如销售记录,要显示单价,售出件数,合计金额等。[/align]
[align=left]我们可以在从数据库中提取数据的时候就使用SQL来产生一个合计字段,也可以在ActiveReport中进行,有两种方法可以使用。[/align]
[align=left]1. 使用ActiveReport中的Label或TextBox控件的DataField属性。例如,要使一个TextBox显示合计,它的值是由单价和售出件数的乘积。设置TextBox的DataField值为“=单价*售出件数”。然后编写代码,加载数据,设置Field集合,然后在FetchData事件中给Field赋值,就可以完成了,例如:[/align]
[align=left]this.Fields["ProductName"].Value = row.productName;[/align]
[align=left]this.Fields["UnitPrice"].Value = row.unitPrice;[/align]
[align=left]this.Fields["Quantity"].Value = row.quantity;[/align]
[align=left]2. 不对DataField属性使用表达式,而是直接在FetchData中进行计算,例如:[/align]
[align=left]double quantity = Convert.ToDouble(this.Fields["Quantity"].Value);[/align]
[align=left]double unitPrice = Convert.ToDouble(this.Fields["UnitPrice"].Value);[/align]
[align=left]this.Fields["ExtendedPrice"].Value = quantity * unitPrice;[/align]
[align=left]当然要在报表上显示要设置Label或TextBox的DataField属性为ExtendedPrice[/align]

[align=left](九)--End User [/align]
[align=left]我们在使用ActiveRepots的时候,通常都是在工程里建一个.rpx文件,然后自动会有一个对应的代码文件,我们就把代码和处理逻辑写在代码文件里。但是,能不能脱离代码文件,只使用.rpx文件来生成报表呢?答案是可以的,ActiveReports提供的EndUser功能可以做到这一点。[/align]
[align=left] [/align]
[align=left]ActiveRepots自带的示例代码中包括了两个EndUser功能的例子:DiamondReports和EndUserDesigner,前者的功能齐备些,后者比较简单,但是对于学习使用EndUser功能,比较直观,下面说说在winform和web环境下如何使用。[/align]
[align=left] [/align]
[align=left]运行EndUserDesigner示例程序,会看到一个在VS.net中的报表设计界面非常相似的界面。有工具栏,有字段列表,有报表布局,有属性,等。实际上最主要的两个控件是ardMain和ardReportExplorer,ardMain就是用来显示报表布局的,ardReportExplorer用来显示当前ardMain的数据源的字段列表和布局的各个部分。[/align]
[align=left] [/align]
[align=left]使用EndUser主要有两个步骤:设定数据源,设计报表布局。设定数据源可以通过点击布局部分Detail字样前的图标,会弹出一个对话框,在这里可以设置数据源类型,连接串,sql语句。完成后会在字段列表部分显示出通过sql语句得到的字段,然后就可以设计报表布局了。你可以把字段列表中的某一项拖放到布局上,会自动生成控件并绑定DataField。[/align]
[align=left] [/align]
[align=left]在Winform下,设计完成后就可以通过EndUserDesigner菜单上的“预览”看到你的报表了。然后可以用Save Layout菜单将报表保存为一个.rpx文件。要在web环境下使用刚才设计的报表,步骤要复杂些:[/align]
[align=left]1. 按照上面的步骤设计.rpx文件。[/align]
[align=left]2. 在web项目中包括.rpx文件。[/align]
[align=left]3. 配置web.config文件,为了能在浏览器中直接显示报表,需要对Web.config文件作一些设置,在system.web 标记里添加以下内容:[/align]
<httpHandlers>
<!--
********** ActiveReports HttpHandler Configuration **********
-->
<add verb="*" path="*.rpx"
type="DataDynamics.ActiveReports.Web.Handlers.RpxHandler, ActiveReports.Web,
Version=4.0.0.1052, Culture=neutral, PublicKeyToken=cc4967777c49a3ff" />
<add verb="*" path="*.ActiveReport"
type="DataDynamics.ActiveReports.Web.Handlers.CompiledReportHandler,
ActiveReports.Web, Version=4.0.0.1052, Culture=neutral,
PublicKeyToken=cc4967777c49a3ff" />
<add verb="*" path="*.ArCacheItem"
type="DataDynamics.ActiveReports.Web.Handlers.WebCacheAccessHandler,
ActiveReports.Web, Version=4.0.0.1052, Culture=neutral,
PublicKeyToken=cc4967777c49a3ff" />
[align=left]</httpHandlers> [/align]
[align=left]这里的Version和PublicKeyToken都必须正确,如果你不清楚,可以通过管理工具里的.net framework配置工具来查看这些属性。[/align]
[align=left]在ActiveReports的文档里说在VS2005中如果不是使用IIS就可以不用配置,在VS2003里是必须的。但是我在VS2005中,如果不加这段配置还是不行。[/align]
[align=left]4. 在页面上使用,例如:<a href="YourReport.rpx?OutputFormat=pdf">Sample</a>[/align]
[align=left]注意这里传入的参数OutputFormat=pdf,这样会使在浏览器里打开报表生成的pdf文件。[/align]
[align=left]目前ActiveReports只支持pdf和html两种格式,如果你使用excel或者rtf,是没有效果的,都会按照html格式显示。[/align]
[align=left] [/align]
[align=left]上面说了基本的操作,但是如果在sql语句里有参数怎么作呢?怎样向sql语句传递值来取得指定的数据呢?[/align]
[align=left]首先要在sql语句里嵌入参数的表达形式,例如:[/align]
[align=left]Select * from Customers WHERE Country = '<%Country%>'[/align]
[align=left]是不是有些像CodeSmith的代码生成脚本?[/align]
[align=left]下面要作的就是传参数值了,在web下比较简单,使用QueryString,例如,我们把Url写成这样:YourReport.rpx?OutputFormat=pdf& Country=China,一切就OK了。[/align]
[align=left]在Winform下,不用自己传参数值,只要你在运行报表的时候,ActiveReports会自己解析Sql语句,分析出有哪些参数,然后会弹出一个对话框,列出参数,要求你输入值。[/align]
[align=left] [/align]
[align=left]可以看出,使用EndUser功能是很简单的,但是它一样也有局限,就是适合较简单的业务,虽然设计一个报表很简单,甚至可以把一部分工作交给客户自己完成,但是不要指望客户能作多么复杂的东西,客户宁可打个电话要求开发者帮忙义务劳动下,维护的工作量最终还是在程序员身上。[/align]

[align=left](十)--交叉变换背景 [/align]
[align=left]在报表中使每条记录按照不同的背景色显示能够增加报表的美观,数据的显示更清晰,这样的效果在报表开发中是很常见的,在ActiveReports中要实现起来也很简单的。[/align]
[align=left]可以像帮助里的例子一样:[/align]
[align=left]bool changeColor = false;[/align]
[align=left]private void Detail_Format(object sender, System.EventArgs eArgs) [/align]
[align=left]{[/align]
[align=left] if (changeColor) [/align]
[align=left] {[/align]
[align=left] changeColor = false; [/align]
[align=left] this.Detail.BackColor = System.Drawing.Color.DarkOrange; [/align]
[align=left] } [/align]
[align=left] else [/align]
[align=left] { [/align]
[align=left] this.Detail.BackColor = System.Drawing.Color.Transparent;[/align]
[align=left] changeColor = true; [/align]
[align=left] } [/align]
[align=left]}[/align]
[align=left]也可以在每条记录的下面放一个Shape,设置其不显示边框,将其置于最后面,然后按照上面的代码方式设置这个Shape的颜色。[/align]
[align=left] [/align]

[align=left](十一)--迁移到3.0 [/align]
[align=left]在这里先介绍下ActiveReports。ActiveReports是.net下出色的报表开发工具,我最喜欢它的地方就是提供了单独的代码文件,你能够操作数据源,也可以控制报表的显示等等,很灵活。但是可能由于宣传不足,国内用的比较少,这两天用上了最新的ActiveReports for .net 3.0,发现比起2.0,变化是比较大的,要从2.0迁移到3.0,还要费一点功夫。下面说说升级后的主要区别和要注意的几个地方,其中包含了一些朋友在本系列前面的随笔的评论中提到的问题。[/align]
[align=left] [/align]
[align=left]安装:[/align]
[align=left]我的安装过程可谓是一波三折。先卸载掉了2.0,安装3.0后发现VS2005每次启动后都提示“包加载错误”,要求使用“devenv /resetskippkgs”重新加载的提示。所有的窗体都无法打开设计器,而且给项目添加新项的时候也没有显示ActiveReports的文件。根据提示在网上搜了一遍,按照微软提供的资料也无法解决,无奈之下只好修复VS2005,完成后窗体设计器可以打开了,这才松了口气,重新安装ActiveReports,这次没有出现什么问题,一次OK。[/align]
[align=left]安装完了,第一件事就是打开帮助看看有什么新的变化,但是很不幸,帮助无法打开,只好又执行了一次帮助安装目录下的H2Reg.exe /r,才把帮助搞定。[/align]
[align=left]这下整个安装过程才完成,可以正式开始了。[/align]
[align=left] [/align]
[align=left]可视化设计器:[/align]
[align=left]设计器中最明显的变化就是添加了“Preview”的Tab页,可以设计好布局后直接在这里预览。3.0版本还在工具栏里提供了在设计期放大,缩小浏览布局的按钮,刚安装后并不显示,需要在工具栏配置中选中。这是个很方便的功能,因为在作一些表格式的报表时,经常在设计期看到线都是对齐的,但是在打印出来后常常有中断或者偏差,有了这个功能,在设计期就能方便地检查这些错误。[/align]
[align=left]还有就是在2.0中,打开报表设计器的时候会显示ReportExplore,现在ReportExplore设计成和类解决方案,属性等窗口一样的模式,可以和这些窗口重叠在一起显示。ReportExplore中的Fileds节点增加了下级:Bound和Caculated。[/align]
[align=left] [/align]
[align=left]代码迁移:[/align]
[align=left]在3.0版本中,程序集名称,命名空间都已经变了,以前用2.0写的报表都编译不了,如果仍然要使用rpx+cs文件的方式,就要自己修改代码,重新添加项目引用。3.0中也提供了工具,用来转换2.0下的报表。该工具是“工具”菜单下的ActiveRepots File Convert,根据向导转换完成后,你会发现,原先的报表的图表变成了和组件一样的图标,原来的Rpx文件已经不存在了,一个报表的文件组成变成了.cs + resx,同样你如果新建一个报表,也是cs+resx这样的文件组合。这应当是3.0中最大的变化了,所以如果你安装了3.0后,看到原来的rpx文件的图标是未知文件类型的,请不要奇怪。[/align]
[align=left]3.0中还提供了从Access导入报表的功能,你可以在给项目添加新项的时候看到“ActiveReports 3.0 Access Import Wizard”的项,提供了一个向导来从指定的Access库中导入报表。[/align]
[align=left] [/align]
[align=left]问题[/align]
[align=left]ActiveReport提供了一个很重要的功能-End User,并且有一个示例程序,实现了一个报表设计器。在这个示例程序中,如果使用了中文字段名,并且显示在Report Explore的Fileds节点中,从Report Explore向报表上拖放的时候会产生一个错误,提示控件名不合法。[/align]
[align=left]这是因为在拖放的时候会自动生成一个和字段名相像的TextBox框,名字为“txt+字段名”,所以会报出错误。但是在2.0中却没有这个错误,当出现中文字段名时,生成对应的TextBox会自动更名,使用合法的名字。所以这应当是3.0中的一个bug。[/align]
[align=left]要重现这个bug,只需要在EndUser示例的窗口的Load事件中添加下面的代码:[/align]
[align=left]DataTable dt = new DataTable();[/align]
[align=left]dt.Columns.Add("中国");[/align]
[align=left]dt.Columns.Add("123123");[/align]
[align=left]dt.Columns.Add("asdf");[/align]
[align=left]dt.TableName = "table1";[/align]
[align=left]DataSet ds = new DataSet();[/align]
[align=left]ds.Tables.Add(dt);[/align]
[align=left] [/align]
[align=left]this.arDesigner.Report.DataSource = ds;[/align]
[align=left]this.arDesigner.Report.DataMember = ds.Tables[0].TableName;[/align]
[align=left]程序启动后会在Report Explore中看到添加的字段,直接拖放到报表上就能看到错误了。[/align]
[align=left]虽然有这个问题,但是并不妨碍使用中文字段,只要不使用拖放功能就可以了。[/align]
[align=left] [/align]
[align=left]粗略的看了下,捡自己觉得重要的写了。完整的更新列表还请看帮助里的“What’s New”。最新版的ActiveReports for .net 3.0可以在DataDynamic的官方网站上下载,已经是带SP1的了。[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: