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

 

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

下次我们将演示如何在报表上加载和显示数据
 
(二)--绑定数据源 
上篇随笔 中写了一个使用 ActiveReport for .net 的最简单的例子,本文将演示在 ActiveReport 中如何绑定数据源
 
1.        先建一个表 chartingTable ,有两个字段, OnlineUserCount Project ,通过向导生成 DataSet ,并拖放生成 TableAdapter
2.        接下来在报表设计器中设计显示格式,在 PageHeader 中放置两个 label ,分别为 项目 在线人数 。再在 Detail 区方式两个对应的 Label ,分别设置 DataFiled Project OnlineUserCount ,在运行的时候将会看到这两个 Label 显示的是对应字段中的内容。
3.        可以给报表指定 DataSet DataView 作为数据源,下面演示给报表设置数据源:
使用 DataSet
this .chartingTableTableAdapter.Fill(this.dataSet1.ChartingTable);
rpt.DataSource = this.dataSet1;
rpt.DataMember = this.dataSet1.ChartingTable.TableName;
rpt.Run();
this .viewer1.Document = rpt.Document;
使用 DataView
this .chartingTableTableAdapter.Fill(this.dataSet1.ChartingTable);
DataView dv = this.dataSet1.ChartingTable.DefaultView; ;
rpt.DataSource = dv;
dv.RowFilter = "project ='1'";
rpt.Run();
this .viewer1.Document = rpt.Document;
4.          我们还可以通过报表设计器来给报表指定数据源。
在报表设计器的 Detail 部分的头部,有一个数据库一样的小图标,点击它后会出现向导,按照向导一步步连接数据库,并定义查询就可以了。
 
上面演示的是使用数据集作为数据源进行绑定,但是实际项目中经常会用到使用对象集合作为数据源显示,下一次我们将演示如何在报表上显示一个对象集合中的数据。
 
 
(三)--显示对象集合中的数据 
将通过一些示例代码继续演示如何绑定对象集合以及如何从对象集合或列表中提取数据。
1.        直接绑定:
我们可以自己定义一个 Collection ,从 IList 继承,并使其中的每个对象都是一个实体,例如:
Customer CustomerCollection 。然后给 ActiveReport 报表的 DataSource 直接赋值为 CustomerCollection 的实例就可以了。这种绑定方法在 ActiveReport for .net 自带的例子里有完整的演示。
2.        手工加载显示对象的数据:
在这里要用到两个事件: DataInitialize FetchData
DataInitialize 用来定义字段列表,获取数据等工作, FetchData 用来指定每个字段的值。
我们简单定义一个 Customer
public class Customer
        {
                public int ID;
                public string Name;
                public string Address;
    }
再给报表定义一个 Customer 数组,用来保存要显示的数据,比如:
public Customer[] customers;
还需要一个值来保存当前记录的索引: private int index =0;
接下来在 DataInitialize 中定义报表有那些字段 :
this .Fields.Add("Name");
    this.Fields.Add("Address");
然后在 FetchData 事件中添加以下代码:
if (this.index >= this.customers.Length )
        {
                eArgs.EOF = true;
                return;
        }
        else
        {
                eArgs.EOF = false;
        }
        this.Fields["Name"].Value = customers[this.index].Name;
        this.Fields["Address"].Value = customers[this.index].Address;
    this.index += 1;
这段代码的含义就是将 Customer 数组中的每个 Customer 实例的 Name Address 属性值赋给报表的 Name Address 字段。
代码中的第一个 if 分支是判断是否已经加载到了最后一条数据,如果是,设置 eArgs.EOF ture ,并返回,否则继续加载下一条数据。
然后我们可以将要显示的数据放在 Customers 数组中,并启动显示报表:
Customer [] customers = new Customer[2];
        Customer c = new Customer();
        c.Name = "James";
        c.Address = "Noljadfallsjf";
        Customer c2 = new Customer();
        c2.Name = "Joe";
        c2.Address = "adfaafadf";
        customers[0] = c;
        customers[1] = c2;
                       
        rpt.customers = customers;
        rpt.Run();
    this.viewer1.Document = rpt.Document;
 
通过上面的示例可以看到,第二种方式虽然比较烦琐,需要程序员自己处理很多东西,但是这样程序员拥有完全的操控能力,特别是需要对取出的数据作很多复杂的处理时,这样的操控能力是非常重要的。
 
在下一篇随笔中,将展示如何使用子报表来作显示主从表。
 
 
(四)显示主从表
上篇随笔 演示了在 ActiveReport for .net 中如何从对象集合中提取数据。本文简单介绍如何使用子报表来显示主从表中的数据。
 
1.        在需要显示主从表中的数据时,使用子报表能够提供很大的灵活性,一般就是把主表的信息显示在 detail 中,如果要每页的上方都要显示主表,就可以放在 PageHeader 中。再把子表的信息放在 Detail 中,然后把子报表中的控件直接绑定到数据源上或者使用上篇随笔中的提到的方式从对象集合中提取数据。
2.        使用子报表:
新建报表,然后在工具箱上可以看到 SubReport 控件,拖放一个控件到 Detail 部分,用此控件来加载子报表。
再新建一个报表,命名为 SubReport1 ,接下来在主报表中写代码,在页面设计器上选中 Detail 部分,在属性窗口切换到事件栏,双击 Format ,将会产生 Detail_Format 事件,下面就要在这个事件里指定子报表控件所要加载的报表。
3.        由于 Detail 部分会进行重复显示的,所以,只能指定一次报表源,在这里,我们按照下面的例子:
ActiveReport sub = null;
private void Detail_Format(object sender, System.EventArgs eArgs)
{
        if ( sub == null )
        {
                sub = new ActiveReports2();
                this.SubReport.Report = sub;
        }
}
先定义一个全局的子报表,然后在 Detail_Format 事件中对其进行初始化。
4.        还有要注意的一点是,在使用完子报表后要将其释放,销毁掉,具体的代码放在主报表的 ReportEnd 事件中,例如:
private void ActiveReports1_ReportEnd(object sender, System.EventArgs eArgs)
{
    sub.Document.Dispose();
sub.Dispose();
sub = null;
}
5.        下面剩下的工作就是摆放控件并设置显示的字段了,加载数据等等了, 前面的随笔 都有介绍。
 
下篇随笔中将介绍如何使用 ActiveReport for .net 开发交叉报表。
 
 
(五)交叉报表  
交叉报表是一种常见的报表类型,而且开发起来也是比较烦琐的一种报表,在 ActiveReport 中,对交叉报表提供了足够的灵活性,使你能够应对各种复杂的业务逻辑。在上篇随笔演示了显示主从表后,本篇随笔简单介绍如何制作交叉报表。
交叉报表的一个常见应用就是用作显示销售额的报表上,例如,显示多个连锁店一年内每个月的销售额,常把月份作为列来显示,每个店用一行来表示 :
店名      1       2           3         4      ……………   
AC       500       200         10000       50000    ……………
BC       511       85245        4545      124578    ……………
但是在数据库中的存储常常采用下面的方式
Sales         Month         Shop
12312           1            AB
243423          2            AB
323232          3            AB
1231312         1            BC
1232            2            BC
这样就需要在显示前对数据进行处理,把销售额和月份转换到列上,我们可以在取数据时使用 sql 来进行这些操作,在这里,为了演示在 activeReport 中的使用,把转换放到报表里来作,为了简化例子,我们只显示第一个季度每月的销售额。
1.       取数据:
使用 Select Sales,Month,Shop from CrossReport Order by Shop 这样的 sql 直接取数据,不作任何合计或转换处理。
2.       转换:
我们来定义一个简单的对象来表示最终要显示的记录 :
public class Sale
{
    public decimal money1; // 一月
    public decimal money2; // 二月
    public decimal money3; // 三月
    public string shopname;
}
同时在定义一个 Sale 的集合 sales ,来保存转换后的数据。
由于在表中每个店会对应多条记录,为了把多条记录合并为一条,要进行下面的转换动作:
// 用来保存已经计算过的店铺,保证每个店铺只有一条记录
ArrayList shopname = new ArrayList();
while (dr.Read())
{
        if (!shopname.Contains(dr.GetString(2))) // 该店铺的第一条记录
        {
                Sale s = new Sale ();
        s.shopname = dr.GetString(2); // 取店名  shopname.Add(s.shopname);
                if (dr.GetInt32(1) == 1) // 一月
                {
                        s.money1 = dr.GetDecimal(0);
}
                else if (dr.GetInt32(1) == 2) // 二月
                {
                        s.money2 = dr.GetDecimal(0);
                }
                else if (dr.GetInt32(1) == 3) // 三月
                {
                        s.money3 = dr.GetDecimal(0);
                }
                sales.Add(s);
        }
        else // 不是该店铺的第一条记录
        {
                Sale s = (Sale)sale [sales.Count - 1];
                if (dr.GetInt32(1) == 1)
                {
                        s.money1 = dr.GetDecimal(0);
}
                else if (dr.GetInt32(1) == 2)
                {
                        s.money2 = dr.GetDecimal(0);
                }
                else if (dr.GetInt32(1) == 3)
                {
                        s.money3 = dr.GetDecimal(0);
                }
        }
}
3.       表示:
上面是对从数据库中取出的记录作转换,将其变成在报表上要显示的格式。接下来就要在报表上显示 Sales 集合中的数据了。我们可以按照前几篇随笔中介绍的方法来作:
n          在界面上摆放控件,并设置其 FiledName 字段
n          在报表的 DataInitialize 事件中设置 Filed 集合,取出数据:
this .Fields.Add("money1");
        this.Fields.Add("money2");
        this.Fields.Add("money3");
        this.Fields.Add("shopname");
this .GetReportData(); // 取数据并作转换
n          设置一个标记来表示是否显示到了最后一条记录 :
int index = 0;
n          FetchData 事件中显示 Sales 集合中的数据:
if (index == sales.Count ) // 如果到了最后一条记录,就跳出
        {
                eArgs.EOF = true;
                return;
        }
        else
        {
                eArgs.EOF = false;
        }
        Sale s = (Sale)sales[index];
        this.Fields["shopname"].Value = s.shopname;
        this.Fields["money1"].Value = s.money1;
        this.Fields["money2"].Value = s.money2;
        this.Fields["money3"].Value = s.money3;
index+=1;
按照上面的步骤,主要的代码都完成了,当然要在窗体上显示,还要加一个 Viewer ,然后指定加载的报表:
ActiveReports1 rpt = new ActiveReports1();
rpt.Run();
this .viewer1.Document = rpt.Document;
如果你不满意显示的效果,可以给报表加上线框,让其显示成表格。
总结:
例子中的代码有重复,但是为了说明转换的过程,没有作优化,另外,也可以看到,代码中使用了 ArrayList ,出现了装箱,拆箱的动作,所以性能还有优化的空间。
从表数据到显示用数据的转换可以在 Sql 中作,但是业务逻辑较复杂的时候, Sql 就显得力不从心,例如,显示每月的数据,而且还有收入,支出,如果再加上税收,折扣,损耗,租金,和上年同期的比较等等无法预测的业务逻辑,如果把 SQL 写在代码中,调试成问题,如果写成存储过程,有破坏了封装。所以相比之下,在代码中进行的转换工作虽然较复杂,但是还是具有灵活的优势的。
 
 
(六)--导出报表 
ActiveReport 提供了多种文件格式的导出,包括 :Html,Pdf,Text,Rtf,Xls Tiff ,这几种格式中, Pdf 是效果最好,因为有了抗锯齿,线条和字体看起来都光滑的多,而且是完全的所见即所得,加上很多 Web 项目都采用 Pdf 作为报表显示的文件格式,导出 Pdf 应该是首选。由于是把报表直接生成了图片, Tiff 格式的导出也是所见即所得的。
 
其他的文件格式的限制都比较多,每种文件格式的限制可以在 ActiveReport 的帮助中搜索 “Limitations in Export Formats” ,其中有详细的列表。
 
将报表导出的步骤也很简单,先要在工具栏上添加导出要用的控件,这组控件有: HtmlExport,PdfExport,RtfExport,TextExport,TiffExport,XlsExport 六种。这里以 PdfExport 为例:
拖放一个 PdfExport 控件到窗体上,就可以进行导出操作了,代码很简单,我们假设有一个报表文件和一个 Viewer
窗体加载的时候:
ActiveReports1 rpt = new ActiveReports1();
rpt.Run();
this .viewer1.Document = rpt.Document;
在一个 Button Click 中:
this .pdfExport1.Export(this.viewer1.Document,@"z:/123.pdf");
很简单吧,其他格式的导出也一样,例如 Excel 格式:
this .xlsExport1.Export(this.viewer1.Document, @"z:/123.xls");
 
在生成 Pdf 的时候要注意,有时页面设置不当,控件的大小可能会超出范围,导致报表有一部分无法打印出来,在使用 AcrobatReader 预览的时候,要在 Print 窗口,通过调整 Page Scaling None ,看看右边 Preview 部分,有没有发生超出打印范围的情况。另外在作表格的时候要放大后看,因为经常会出现线条没有对齐或完全连接的情况,在预览的时候看不出来,但是在打印后会看到线条错位等情况。
 
 
(七)--事件
上篇随笔介绍了在 ActievReport 中导出报表,本篇随笔简单介绍 ActiveReport 中的重要事件。
 
1.        只触发一次的事件:
ReportStart 在报表启动时触发。该事件在 DataInitialize 之前,在这里可以整个报表都要用到的对象或变量作初始化,也可以设置子报表。
DataInitialize :这个事件在前面的几篇随笔中经常出现,经常在这里取数据,绑定数据源,设置报表的 Fileds 属性等。
ReportEnd 在报表加载完成后触发。
2.        多次触发的事件:
FetchData 在处理每一条数据时都会触发,如果是采用绑定数据源的方式,就不需要再作对 Fields 中每个 Field Value 赋值。如果是从自定义的对象集合中提取数据,就要在这里给 Fields 赋值。而且,使用自定义集合的时候要自己设置事件的 eArgs 参数的 EOF 属性,该属性用来判断是否显示到了最后一条记录,如果是,就设置为 true ,并且直接返回。具体的代码可以参看以前的随笔。
PageStart 在报表的每页生成的时候触发,在这里作针对每个页的处理,最常见的就是显示页码。
PageEnd 在报表的每也生成完成的时候触发。
3.        区域的事件:
每个区域( PageHeader Detail PageFooter )都有 Format BeforePrint AfterPrint 事件。最好不要在这几个事件中操作报表的 Fields 集合,而应该在 DataInitialize FetchData 中进行。
Format 在数据加载并绑定后触发,只有在这里才可以设置某个区域的高度。
BeforePrint 在区域被生成前触发,在这里如果设置区域的高度是不会有效果的,而且不要在这里操作数据源。
AfterPrint 在区域已经被生成并描画出后发生,可以在该事件里直接在画布上进行描画操作。
 
 
(八)--显示合计 
在报表开发中我们常常要显示合计,比如销售记录,要显示单价,售出件数,合计金额等。
我们可以在从数据库中提取数据的时候就使用 SQL 来产生一个合计字段,也可以在 ActiveReport 中进行,有两种方法可以使用。
1.        使用 ActiveReport 中的 Label TextBox 控件的 DataField 属性。例如,要使一个 TextBox 显示合计,它的值是由单价和售出件数的乘积。设置 TextBox DataField 值为 “= 单价 * 售出件数 。然后编写代码,加载数据,设置 Field 集合,然后在 FetchData 事件中给 Field 赋值,就可以完成了,例如 :
this .Fields["ProductName"].Value = row.productName;
this .Fields["UnitPrice"].Value = row.unitPrice;
this .Fields["Quantity"].Value = row.quantity;
2.        不对 DataField 属性使用表达式,而是直接在 FetchData 中进行计算,例如:
double quantity = Convert.ToDouble(this.Fields["Quantity"].Value);
double unitPrice = Convert.ToDouble(this.Fields["UnitPrice"].Value);
this .Fields["ExtendedPrice"].Value = quantity * unitPrice;
当然要在报表上显示要设置 Label TextBox DataField 属性为 ExtendedPrice
 
(九)--End User  
我们在使用 ActiveRepots 的时候,通常都是在工程里建一个 .rpx 文件,然后自动会有一个对应的代码文件,我们就把代码和处理逻辑写在代码文件里。但是,能不能脱离代码文件,只使用 .rpx 文件来生成报表呢?答案是可以的, ActiveReports 提供的 EndUser 功能可以做到这一点。
 
ActiveRepots 自带的示例代码中包括了两个 EndUser 功能的例子: DiamondReports EndUserDesigner ,前者的功能齐备些,后者比较简单,但是对于学习使用 EndUser 功能,比较直观,下面说说在 winform web 环境下如何使用。
 
运行 EndUserDesigner 示例程序,会看到一个在 VS.net 中的报表设计界面非常相似的界面。有工具栏,有字段列表,有报表布局,有属性,等。实际上最主要的两个控件是 ardMain ardReportExplorer ardMain 就是用来显示报表布局的, ardReportExplorer 用来显示当前 ardMain 的数据源的字段列表和布局的各个部分。
 
使用 EndUser 主要有两个步骤:设定数据源,设计报表布局。设定数据源可以通过点击布局部分 Detail 字样前的图标,会弹出一个对话框,在这里可以设置数据源类型,连接串, sql 语句。完成后会在字段列表部分显示出通过 sql 语句得到的字段,然后就可以设计报表布局了。你可以把字段列表中的某一项拖放到布局上,会自动生成控件并绑定 DataField
 
Winform 下,设计完成后就可以通过 EndUserDesigner 菜单上的 预览 看到你的报表了。然后可以用 Save Layout 菜单将报表保存为一个 .rpx 文件。要在 web 环境下使用刚才设计的报表,步骤要复杂些:
1.        按照上面的步骤设计 .rpx 文件。
2.        web 项目中包括 .rpx 文件。
3.        配置 web.config 文件,为了能在浏览器中直接显示报表,需要对 Web.config 文件作一些设置,在 system.web 标记里添加以下内容:
<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" />
</httpHandlers>
这里的 Version PublicKeyToken 都必须正确,如果你不清楚,可以通过管理工具里的 .net framework 配置工具来查看这些属性。
ActiveReports 的文档里说在 VS2005 中如果不是使用 IIS 就可以不用配置,在 VS2003 里是必须的。但是我在 VS2005 中,如果不加这段配置还是不行。
4.        在页面上使用,例如: <a href="YourReport.rpx?OutputFormat=pdf">Sample</a>
注意这里传入的参数 OutputFormat=pdf ,这样会使在浏览器里打开报表生成的 pdf 文件。
目前 ActiveReports 只支持 pdf html 两种格式,如果你使用 excel 或者 rtf ,是没有效果的,都会按照 html 格式显示。
 
上面说了基本的操作,但是如果在 sql 语句里有参数怎么作呢?怎样向 sql 语句传递值来取得指定的数据呢?
首先要在 sql 语句里嵌入参数的表达形式,例如:
Select * from Customers WHERE Country = '<%Country%>'
是不是有些像 CodeSmith 的代码生成脚本?
下面要作的就是传参数值了,在 web 下比较简单,使用 QueryString ,例如,我们把 Url 写成这样: YourReport.rpx?OutputFormat=pdf& Country=China ,一切就 OK 了。
Winform 下,不用自己传参数值,只要你在运行报表的时候, ActiveReports 会自己解析 Sql 语句,分析出有哪些参数,然后会弹出一个对话框,列出参数,要求你输入值。
 
可以看出,使用 EndUser 功能是很简单的,但是它一样也有局限,就是适合较简单的业务,虽然设计一个报表很简单,甚至可以把一部分工作交给客户自己完成,但是不要指望客户能作多么复杂的东西,客户宁可打个电话要求开发者帮忙义务劳动下,维护的工作量最终还是在程序员身上。
 
(十)--交叉变换背景  
在报表中使每条记录按照不同的背景色显示能够增加报表的美观,数据的显示更清晰,这样的效果在报表开发中是很常见的,在 ActiveReports 中要实现起来也很简单的。
可以像帮助里的例子一样:
bool changeColor = false;
private void Detail_Format(object sender, System.EventArgs eArgs)
{
        if (changeColor)
        {
                changeColor = false;
                this.Detail.BackColor = System.Drawing.Color.DarkOrange;
        }
        else
        {
                this.Detail.BackColor = System.Drawing.Color.Transparent;
                changeColor = true;
        }
}
也可以在每条记录的下面放一个 Shape ,设置其不显示边框,将其置于最后面,然后按照上面的代码方式设置这个 Shape 的颜色。
 
 
(十一)--迁移到3.0  
在这里先介绍下 ActiveReports ActiveReports .net 下出色的报表开发工具,我最喜欢它的地方就是提供了单独的代码文件,你能够操作数据源,也可以控制报表的显示等等,很灵活。但是可能由于宣传不足,国内用的比较少,这两天用上了最新的 ActiveReports for .net 3.0 ,发现比起 2.0 ,变化是比较大的,要从 2.0 迁移到 3.0 ,还要费一点功夫。下面说说升级后的主要区别和要注意的几个地方,其中包含了一些朋友在本系列前面的随笔的评论中提到的问题。
 
安装:
我的安装过程可谓是一波三折。先卸载掉了 2.0 ,安装 3.0 后发现 VS2005 每次启动后都提示 包加载错误 ,要求使用 “devenv /resetskippkgs” 重新加载的提示。所有的窗体都无法打开设计器,而且给项目添加新项的时候也没有显示 ActiveReports 的文件。根据提示在网上搜了一遍,按照微软提供的资料也无法解决,无奈之下只好修复 VS2005 ,完成后窗体设计器可以打开了,这才松了口气,重新安装 ActiveReports ,这次没有出现什么问题,一次 OK
安装完了,第一件事就是打开帮助看看有什么新的变化,但是很不幸,帮助无法打开,只好又执行了一次帮助安装目录下的 H2Reg.exe /r ,才把帮助搞定。
这下整个安装过程才完成,可以正式开始了。
 
可视化设计器:
设计器中最明显的变化就是添加了 “Preview” Tab 页,可以设计好布局后直接在这里预览。 3.0 版本还在工具栏里提供了在设计期放大,缩小浏览布局的按钮,刚安装后并不显示,需要在工具栏配置中选中。这是个很方便的功能,因为在作一些表格式的报表时,经常在设计期看到线都是对齐的,但是在打印出来后常常有中断或者偏差,有了这个功能,在设计期就能方便地检查这些错误。
还有就是在 2.0 中,打开报表设计器的时候会显示 ReportExplore ,现在 ReportExplore 设计成和类解决方案,属性等窗口一样的模式,可以和这些窗口重叠在一起显示。 ReportExplore 中的 Fileds 节点增加了下级: Bound Caculated
 
代码迁移:
3.0 版本中,程序集名称,命名空间都已经变了,以前用 2.0 写的报表都编译不了,如果仍然要使用 rpx cs 文件的方式,就要自己修改代码,重新添加项目引用。 3.0 中也提供了工具,用来转换 2.0 下的报表。该工具是 工具 菜单下的 ActiveRepots File Convert ,根据向导转换完成后,你会发现,原先的报表的图表变成了和组件一样的图标,原来的 Rpx 文件已经不存在了,一个报表的文件组成变成了 .cs + resx ,同样你如果新建一个报表,也是 cs+resx 这样的文件组合。这应当是 3.0 中最大的变化了,所以如果你安装了 3.0 后,看到原来的 rpx 文件的图标是未知文件类型的,请不要奇怪。
3.0 中还提供了从 Access 导入报表的功能,你可以在给项目添加新项的时候看到 “ActiveReports 3.0 Access Import Wizard” 的项,提供了一个向导来从指定的 Access 库中导入报表。
 
问题
ActiveReport 提供了一个很重要的功能- End User ,并且有一个示例程序,实现了一个报表设计器。在这个示例程序中,如果使用了中文字段名,并且显示在 Report Explore Fileds 节点中,从 Report Explore 向报表上拖放的时候会产生一个错误,提示控件名不合法。
这是因为在拖放的时候会自动生成一个和字段名相像的 TextBox 框,名字为 “txt+ 字段名 ,所以会报出错误。但是在 2.0 中却没有这个错误,当出现中文字段名时,生成对应的 TextBox 会自动更名,使用合法的名字。所以这应当是 3.0 中的一个 bug
要重现这个 bug ,只需要在 EndUser 示例的窗口的 Load 事件中添加下面的代码:
DataTable dt = new DataTable();
dt.Columns.Add(" 中国 " );
dt.Columns.Add("123123");
dt.Columns.Add("asdf");
dt.TableName = "table1";
DataSet ds = new DataSet();
ds.Tables.Add(dt);
 
this .arDesigner.Report.DataSource = ds;
this .arDesigner.Report.DataMember = ds.Tables[0].TableName;
程序启动后会在 Report Explore 中看到添加的字段,直接拖放到报表上就能看到错误了。
虽然有这个问题,但是并不妨碍使用中文字段,只要不使用拖放功能就可以了。
 
粗略的看了下,捡自己觉得重要的写了。完整的更新列表还请看帮助里的 “What’s New” 。最新版的 ActiveReports for .net 3.0 可以在 DataDynamic 的官方网站上下载,已经是带 SP1 的了。
 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值