通常情况下数据源中会含有大量数据,而一张报表会根据用户的需要展示其中的一小部分。这时您需要使用筛选来选择用户需要的数据,比如在显示客户信息表时,我们可以根据用户需要,使用筛选让报表只显示某个特定地区的数据。您甚至可以让用户在运行报表时指定一个值做为筛选值来筛选数据。本章将讨论在BIRT报表中如何使用筛选。出于报表性能方面的考虑,我们建议您在设计报表时仅从数据源获取制作报表需要使用的数据。根据数据源类型与您制作报表类型的不同,BIRT报表提供了多种方法来筛选数据。筛选的第一个时机是使用您数据源提供的筛选功能。比如支持 JDBC 的数据库可以让用户在SQL 查询语句中加入WHERE 子句来筛选数据。事实上,使用数据库的筛选功能来筛选数据的性能是最优的。在BIRT报表从数据源取回数据之后,在报表设计的许多地方您还可以设置筛选,至于在什么地方、什么时候来筛选则大大取决于您自己的需要。比如一个表格和一个列表包含了相似的数据,仅仅是筛选条件不同,那么您可以只创建一个数据集,然后在表格和列表上分别做筛选,而不用为表格和列表各做一个数据集。因为前一种情况只访问数据库一次。
当您使用 JDBC 数据源创建SQL SELECT 查询类型的数据集时,您可以在SELECT查询语句中加入WHERE 条件子句来从数据库查询数据,您可以在WHERE 条件子句定义查询条件,从而实现对数据库中的数据进行筛选。比如下面的 SQL 语句让数据库仅返回客户国家为China 的客户信息:
SELECT *
FROM Customer
WHERE country = 'China'
而下面的SQL 语句则让数据库仅返回客户国家为China,且信用额度超过10000 的客户信息:
SELECT customerName
FROM Customer
WHERE country = 'China'
AND creditLimit > 10000
假定您已经创建了 JDBC 数据源并使用该数据源创建了SQL SELECT 查询数据集。在数据资源管理器中,双击您需要添加筛选的数据集,打开“编辑数据集”窗口。在查询页面的 SQL 语句编辑区中,添加一个WHERE 子句并定义您的筛选条件。点击“预览结果”,查看数据集返回的结果是否按照您定义的筛选条件进行了筛选。
关于如何编写 SQL WHERE 语句,请查阅SQL 相关资料。
当您使用 XML 数据源创建数据集时,您需要将XML 元素与属性映射至数据集列来指定从XML 中获取哪些数据。为了将XML 元素或属性映射至列,您需要编写XPath。XPath是XML 的查询语言,如果您对XPath 不熟悉,建议您先去了解XPath 的相关资料。
筛选XML 数据源中的数据时,您可以在XPath 语句中指定一个筛选值来筛选数据,比如下面的XPath 语句则让数据源只返回作者名字为”Sally Bush”的信息。
Author[@name=”Sally Bush”]
除了设置在数据源中筛选数据外,您还可以在其他地方筛选数据。当然,我们建议您尽可能在数据源中筛选数据,但是有些数据源中,比如扁平文件数据源,你就不能在数据源中筛选数据。这样您需要在BIRT报表中筛选数据。另外,有些时候SQL 的WHERE 子句并不能满足您的筛选需求,而BIRT报表提供了更多的筛选功能,并且提供了一个可视化的筛选编辑工具来帮助您对数据进行筛选
下面是您在BIRT报表可以设置筛选的地方,您可以在任意一个或多个地方设置筛选
� 数据集
� 报表元素,如表格或列表
� 组
BIRT报表中筛选的第一时机是在数据集上。当报表中只有一个元素使用该数据集,或者当报表中所有元素使用的数据都一样时,您可以在数据集上设置筛选。下图设置了数据集上的过滤器,选择国家为’USA’,城市为’NJ’:
接下来您可以在报表元素上设置筛选。您可以编辑报表元素的筛选属性来指定该元素显示哪些数据。当报表中有多个表格、列表或图表使用同一个数据集,但各自只展现数据集中一部分特定数据的时候,您可以在报表元素上设置筛选。比如您创建了一个数据集,该数据集返回所有国家为 USA 的客户信息。然后在报表设计中有两个报表元素使用了该数据集,比如一个表格和一个列表,那么您可以在表格和列表上分别设置筛选,让它们显示不同的信息。
如下图,我们表的属性中设置了2个过滤器,分别为:
row["CREDITLIMIT"] Top n 100
row["COUNTRY"] 等于 "Canada"
预览结果如下:
最后,您可以在分组上设置筛选。如果您在表格或列表中创建了分组,那么您可以在“创建组”或“编辑组”窗口的筛选标签页里设定分组的筛选,来让表格或列表只显示符合特定条件的分组。比如按客户分组的销售订单统计报表,您可以设定只显示总计订购额达到某个值的客户的订单信息,而不用显示所有客户的订单信息。
如前所述,在BIRT报表中您有三个地方可以设置筛选,您可以根据需要来选择在什么地方设置筛选。以下就是我们给您的几点建议:
� 当您在数据集上设置筛选时,BIRT报表是对数据源取回所有数据进行筛选。
� 当您在报表元素上设置筛选时,BIRT报表是对与该报表元素绑定的数据集中的所有数据进行筛选。
� 当您在分组上设置筛选时,BIRT报表是对组级别的数据进行筛选,通常我们会在筛选条件中使用聚合表达式。比如在前面的例子中,您在分组上设置筛选时,您可以对每个组的国家名或客户总数进行筛选;而不可以对客户名称或客户电话等属于组内明细数据进行筛选。
� 凡是在筛选条件中使用了聚合表达式的筛选只能应用在分组上。在某些情况下同样的筛选条件被设置在不同的地方会产生同样的结果。比如在前面的例子中,您想只显示国家名以A 开头的各个国家的客户信息,那么您可以在数据集、表格或分组上设置同样的筛选条件来达到这一效果。
在BIRT报表中,您可以根据需要创建不同的筛选条件类型来对数据进行筛选,比如您可以设置筛选条件让BIRT报表返回数据中指定列值等于一个特定的值的所有行,或者返回指定列值位于一个特定区间内的所有行,再或者返回指定列值与一个特定字符串模式匹配的所有行等等。
在设置筛选时,BIRT报表把筛选条件运算符直接以名称的方式给您显示,而非实际的运算符,比如BIRT报表直接显示名称“大于”,“小于”,“类似”等,而不是>, <, like 等。下面的表格给您列出了BIRT报表支持的各种筛选条件类型。大多数的筛选运算符可以应用在所有数据类型上。需要注意的是在这些运算符当中有两个模式匹配运算符:类似与匹配(like 与match)。“类似”运算符可以让熟悉SQL 的用户使用SQL 语法来指定模式匹配表达式。而“匹配”运算符则让熟悉JavaScript 的用户使用JavaScript 正则表达式语法来指定模式匹配表达式。
筛选条件 |
描述 |
示例 |
比较 |
比较字段值与指定值 |
row["quantity"] 小于 10 row["custName"] 等于 "Acme Inc." row["custName"] 大于或等于"P" row["custState"] 不等于 "CA" row["orderDate"] 小于或等于 "06/30/05" |
空值 |
测试字段值是否为空 |
row["manager"] 为Null row["shipDate"] 不为Null |
区间 |
测试字段值是否在指定区间内,区间两端包含在内 |
row["quantity"] 介于 50 与 100 row["custName"] 介于 "A" 与 "B" row["custName"] 不介于 "A" 与 "M" row["orderDate"] 介于"06/01/05" 与 "06/30/05" |
条件逻辑 |
测试筛选条件表达式为真或假 |
row["country"] == "USA"|| row["country"]== "Canada" 为假 row["orderStatus"] == "Open"||row["orderTotal"] > 100000 为真 |
模式匹配测试(JavaScript语法) |
测试字符串值与指定正则表达式是否匹配 |
row["custName"] 匹配 /Smith/(返回所有列custName 包含有Smith 的行) row["creditRank"] 匹配 /[AB]/(返回信用级别包含A 或B 的行)row["productCode"] 匹配 /^S10/(返回产品编号以S10 开头的行) |
模式匹配测试(SQL 语法) |
测试字符串值与指定模式是否匹配 |
row["custName"] 类似 "%Smith%" row["productCode"] 类似 "S10%" |
上n 或下n 逻辑 |
测试列值是否位于前n 或后n 名 |
row["age"] 上百分比 5 row["age"] 下百分比 5 row["orderTotal"] 上 n 10 row["orderTotal"] 下 n 10 |
筛选条件的右边的输入框,可以输入常量,也可以由数据集构建或由表达式生成器构造,方便后期维护人员知晓业务逻辑。
同过滤,排序可以是数据集上的排序,也可以是表上的排序,下图添加了两个排序依据:
row["CUSTOMERNUMBER"] 升序
row["CUSTOMERNAME"] 升序
BIRT报表以及一些数据库在对字符串排序时,会按它们的 UCS2 码来排序,因此所有大写字母都会排在消协字母前面,比如”Z”排在”a”前面,下面是一个BIRT报表对字符串进行升序排序的例子:
ANG Resellers
AV Stores, Co.
Alpha Cognac
American Souvenirs Inc
Anna’s Decorations, Ltd
abc Shops
而大多数时候,报表用户在查看字符串数据时,比如查看客户名称列表时,希望它们按照字母来排序,而不作大小写区分。为了达到这个效果,您可以在BIRT报表中使用JavaScript函数toUpperCase()或者toLowerCase(),将排序关键字全部转为大写或小写后,再进行排序。下面是一个排序关键字表达式的例子:
Row[“CUSTOMERNAME”].toUpperCase()
如果您在添加排序依据时使用该表达式作为排序关键字,那么上面的排序结果就变为:
abc Shops
Alpha Cognac
American Souvenirs Inc
ANG Resellers
Anna’s Decorations, Ltd
AV Stores, Co.
BIRT自身也提供javascript库处理字符串,如下图
我们可以在此构建更复杂的表达式,实现动态交互排序,
先建立一个静态组合框参数srt
然后在表的过滤器中添加一个过滤条件:
键的内容如下:
if( params["srt"].value == "firstcol" ){
row["CUSTOMERNUMBER"];
} else if( params["srt"].value == "secondcol"){
row["CUSTOMERNAME"];
} else if( params["srt"].value == "thirdcol"){
row["CONTACTLASTNAME"];
}
运行报表:
当然,这个构建过程可以放置在数据集中的过滤器中。
当您设置了一个报表元素的格式后,在报表运行生成时它会应用到所有该元素的实例中。比如您设置了表格明细行的一个名为价格的字段的字体为Arial, 颜色为蓝色,那么在报表运行生成后,所有价格字段的字体都为Arial,颜色都为蓝色。这种类型的格式化我们成为绝对格式化,元素的格式在设计时就已经给定了。而BIRT报表还可以让您基于某个数据的值来设置一个元素的格式。过$1,000 的价格的颜色为蓝色,小于或等于$1,000 的显示为默认颜色黑色。这种方式的设置格式我们称为条件格式。
� 创建条件格式
使用BIRT报表设计器的突出显示页面,您可以非常方便的给报表元素设置条件格式,您可以创建一个条件规则,并定义如何更改报表元素的格式。
1. 在报表设计中选中需要设置条件格式的报表元素。
2. 在属性编辑器中选择“突出显示”标签,如下图所示:
表,行,列,单元格,数据项都有突出显示属性卡,下图显示了一个突出显示客户号前10的,背景设置为绿色:
更常用的用法是利用行属性中的突出显示来实现隔行变色,方法如下,条件为row.__rownum%2 等于 0,背景设为浅灰色:
我们新建一个报表SortTable.rptdesign,空白模板,示例数据库,sql选择查询数据源
新建数据集data set
select *
from customers
布局报表,把所有字段依次放置到一个1行13列的表中,做适当的布局和美化,效果如下:
我们再建另一个报表sort_Table2.rptdesign,空白模板,示例数据库,sql选择查询数据源
新建数据集orders:
select a.CUSTOMERNUMBER,a.ORDERNUMBER,a.ORDERDATE,a.REQUIREDDATE,a.SHIPPEDDATE,a.STATUS,
c.PRODUCTNAME,b.QUANTITYORDERED,b.PRICEEACH
from CLASSICMODELS.ORDERS a ,CLASSICMODELS.ORDERDETAILS b,CLASSICMODELS.PRODUCTS c
where a.ORDERNUMBER=b.ORDERNUMBER
and b.PRODUCTCODE=c.PRODUCTCODE
and a.CUSTOMERNUMBER=?
新建参数para1,在数据集中绑定参数占位符到参数para1,默认值为上个报表SortTable.rptdesign数据集中的customernumber中的一个值,本例选114,把customernumber,odernumber,productname,requireddate,dataSetRow["QUANTITYORDERED"]*dataSetRow["PRICEEACH"]依次放置到一个1行4列的表中,做适当的布局和美化,效果如下
预览如下:
我们现在在SortTable.rptdesign报表的customernumber数据项上添加超链接,选中数据项,在属性编辑器视图的超链接标签下,有超链接至:
选择编辑,选择追溯:
依次选择目标文件为sort_Table2.rptdesign,添加参数绑定报表项row["CUSTOMERNUMBER"],在第4步选择相同框架,确定。
预览,我们发现客户号显示为超链接了
单击即可转跳到至sort_Table2.rptdesign报表的显示
这就是报表的追溯功能,也就是钻取功能。
报表还有书签功能,方便报表的内部转跳或者由钻取的时候指定另一个报表的位置。
我们新建报表CustomerOrdersFinal.rptdesign,空白模板,示例数据库,sql选择查询数据源,
新建数据集setCustomerList:
select CLASSICMODELS.CUSTOMERS.CUSTOMERNAME,
CLASSICMODELS.CUSTOMERS.CUSTOMERNUMBER,
CLASSICMODELS.CUSTOMERS.CONTACTLASTNAME,
CLASSICMODELS.CUSTOMERS.CONTACTFIRSTNAME,
CLASSICMODELS.CUSTOMERS.PHONE,
CLASSICMODELS.CUSTOMERS.ADDRESSLINE1,
CLASSICMODELS.CUSTOMERS.ADDRESSLINE2,
CLASSICMODELS.CUSTOMERS.CITY,
CLASSICMODELS.CUSTOMERS.STATE,
CLASSICMODELS.CUSTOMERS.POSTALCODE,
CLASSICMODELS.CUSTOMERS.COUNTRY,
CLASSICMODELS.CUSTOMERS.CREDITLIMIT
from CLASSICMODELS.CUSTOMERS
新建数据集setOrders:
select
CLASSICMODELS.CUSTOMERS.CUSTOMERNAME,
CLASSICMODELS.CUSTOMERS.CUSTOMERNUMBER,
CLASSICMODELS.ORDERS.ORDERNUMBER,
CLASSICMODELS.ORDERS.ORDERDATE,
CLASSICMODELS.ORDERS.STATUS,
CLASSICMODELS.ORDERDETAILS.QUANTITYORDERED,
CLASSICMODELS.ORDERDETAILS.PRICEEACH
from
CLASSICMODELS.CUSTOMERS,
CLASSICMODELS.ORDERS,
CLASSICMODELS.ORDERDETAILS
where
CLASSICMODELS.CUSTOMERS.CUSTOMERNUMBER = CLASSICMODELS.ORDERS.CUSTOMERNUMBER
and
CLASSICMODELS.ORDERS.ORDERNUMBER = CLASSICMODELS.ORDERDETAILS.ORDERNUMBER
and CLASSICMODELS.CUSTOMERS.CUSTOMERNUMBER=?
新建参数para1,默认值为114,绑定setOrders参数至报表参数para1.
我们在布局编辑器中插入一个4行1列的网格,再在网格的第1行插入一个书签,命名Customer Orders,在第2行插入一个1行7列的表,在第3行插入一个标签Customer Listing,在第四行插入一个1行4列的表,分别把setOrders的属性列拖入上面的表中的详细数据列,其中有一列Totalsales绑定dataSetRow["QUANTITYORDERED"] * dataSetRow["PRICEEACH"],把setCustomerList中的属性列拖入下面的表中的详细数据列,保留一列为customername。把第一个表插入分组,分别以customernumber和ordernumber分组,插入聚合统计功能(后文会详解),做适当的布局如下:
我们在第一个表的组数据列的customername数据项上建立书签,取名row["CUSTOMERNAME"]:
我们在第二个表的详细数据列的数据项customername上建立超链接,
选择追溯,绑定参数至row["customernumber"],选择目标定位标记为目标书签row["customernumber"],选择在相同框架下显示目标报表。
预览报表,我们可以看到如下所示:
往后翻我们可以看到客户信息表,其中客户名称是超链接:
点击可以刷新页面打开新的客户订单明细。
书签不必一定要和追溯一起用,也可以用于自身,不必刷新报表。
例如我们可以在客户列表的页眉行customername上建立书签,命名”custmark”:
然后在客户订单详细表的页眉上建立超链接,选择内部书签,选择”custmark”:
预览报表,我们可以在第一页的页眉上点击超链接,转跳到后面的客户信息表:
追溯的本质是什么?
我们在编辑超链接的时候可以选择类型报表类型为URL,用表达式生成器编辑位置为
"../frameset?__report=CustomerOrdersFinal.rptdesign¶1="+row["customernumber"]
同样能实现钻取功能,这说明钻取内部实际上只是一个动态超链接。
不过这种方式在预览和设计器自带的报表查看器中不起作用,会报出如下错误:
+ The report file : /D:/eclipse/plugins/org.eclipse.birt.report.viewer_3.7.2.v20120213/birt///CustomerOrdersFinal.rptdesign does not exist or contains errors.
只有发布到环境中才能生效,这主要是由于报表设计器预览的文件的路径和服务器文件的路径不一致。