(一)--开始
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
的了。