BIRT报表技术

 

Birt 开发文档

目录

一.前言................................................................................................................................................................ 2

二.开发环境安装.......................................................................................................................................... 3

三.报表分类..................................................................................................................................................... 3

1.清单表.......................................................................................................................................................... 4

2.固定格子表............................................................................................................................................... 4

3.交叉表......................................................................................................................................................... 4

4.Chart图表.................................................................................................................................................. 4

四.报表开发..................................................................................................................................................... 5

1.清单表......................................................................................................................................................... 6

2.固定格子表............................................................................................................................................. 17

3.交叉表....................................................................................................................................................... 18

4.Chart图表............................................................................................................................................... 22

五.报表的参数使用.................................................................................................................................. 26

1.Combo box.............................................................................................................................................. 26

2.Radio button........................................................................................................................................... 27

3.List.............................................................................................................................................................. 27

六.报表的级联参数的使用.................................................................................................................. 29

七.模板及自定义js.................................................................................................................................. 32

1.样式模板.................................................................................................................................................. 33

2.自定义js文件....................................................................................................................................... 35

八.报表中script的使用........................................................................................................................ 38

1.在script中对sql的控制.................................................................................................................. 38

2.                                                                                                                                                                                                                                                                  报表中script的控制     42

(1).隔行换色....................................................................................................................................... 42

(2).鼠标高亮......................................................................................................................................... 44

(3).birt所提供常用的script方法.............................................................................................. 46

九.项目开发中整合birt........................................................................................................................ 51

1.Struts2整合问题.................................................................................................................................. 52

2.实现报表的数据权限的控制.......................................................................................................... 58

十.Birt的扩展............................................................................................................................................. 61

1.Birt的页面样式.................................................................................................................................... 62

(1).修改combobox页面............................................................................................................... 63

(2).修改textbox页面...................................................................................................................... 70

(3).按钮样式的修改........................................................................................................................ 75

2.Birt国际化.............................................................................................................................................. 75

十一.Birt的使用小技巧........................................................................................................................ 77

1.报表的返回............................................................................................................................................. 79

2.报表的参数默认值.............................................................................................................................. 80

(1).日报返回系统前一天的8位日期...................................................................................... 80

(2).月报返回系统上个月末8位日期...................................................................................... 82

3.报表web.xml的配置......................................................................................................................... 84

4.报表参数的页面开发......................................................................................................................... 85

(1).参数的传递方式........................................................................................................................ 85

(2).birt标签的使用.......................................................................................................................... 87

①.view标签............................................................................................................................... 87

②.report标签............................................................................................................................ 89

③.param标签............................................................................................................................ 90

④.parameterPage标签.......................................................................................................... 90

⑤.paramDef标签..................................................................................................................... 92

 

一.   前言

BIRT (Business Intelligence and Reporting Tools), 是为 Web 应用程序开发的基于 Eclipse 的开源报表系统,特别之处在于它是以 Java 和 J2EE 为基础。BIRT 有两个主要组件:基于 Eclipse 的报表设计器,以及部署到应用服务器上的运行时组件。

   Birt有以下几点优点:

1、开发方便,Birt是Eclipse的一个插件可以很好的集成在Eclipse中,图形编辑框架下可以在几分钟之内做出一个报表。

2、可以很方便地在一个报表中混合展现概要数据和详细数据。

3、操作界面友好大方。

4、提供了强大灵活的样式定义,对于熟悉CSS的设计人员来说,应该可以设计出相当出色的报表样式。

5、集成在Eclipse中,不用再开启别报表开发工具窗口,对于习惯于Eclipse开发的程序员来说这点非常重要。

6、Birt的本地化做的很好,安装以后操作界面就是中文的(这点我在使用过程中没有充分体现,我使用了Birt的中文语言包)。

7、开源的报表产品,有源代码,可以进行深层的定制开发。

8、生成的报表完全是XML格式,扩展性好。

9、容易和应用系统结合。

10、最重要一点是开源免费的。

 

 

二.   开发环境安装

目前最新的birt版本是4_0_0_M4(2.5.1与2.6.2版本比较稳定,效率较高),为了方便使用可以直接下载安装。

Myeclipse9.1,已经集成好的birt插件,安装好之后可以直接进行开发使用,比较适合程序员的开发习惯,但需注意的是birt2.6需要有JDK1.6的支持(本人使用的是MyEclipse8.0)。

另一种开发birt的环境birt-report-designer-all-in-one是官网所提供的类似于eclipse操作界面的环境,还提供了一个birt运行的一个平台Birt-runtime类似于tomcat服务器一样,同样的也可以在tomcat服务器上运行。

 

 

三.   报表分类

所有报表大致分为四类:清单表、固定格子表、交叉表、chart图表

1.清单表

  也就是最为普遍和简单的报表形式,无需特殊的处理,只需要根据sql语句直接进行展现,数据会自动的向下延展。

2.固定格子表

  所谓固定格子表其实就是一个格子对应一个数据,而对于表的其他的位置可以根据业务需要自由的定义表头,虽然灵活性非常好,但是对于字段数据过多的情况出表的效率还是有点低,不方便维护。

3.交叉表

  交叉表和清单表一样出现的频率较高,交叉表的好处在于后台的灵活度可以提高,因为在前台进行展示的时候,其实只是看到了一个字段而已,但是它会根据后台的数据可以实现自动的向右进行延展灵活程度大大的提高了,对于补录数据也提供了方便。

4.chart图表

  所谓chart就是一种图表技术,它可以让用户更为直观的通过图表俩分析数据的起伏变化,相比于表格来说更容易快速的得到结果,如果图表旁边再配上数据表分析起来就更为了直观了。而birt所提供的图表支持也是较为丰富,例如:饼图、线性图、折线图、柱状图等近十余种图表技术,给用户提供了大量的空间进行开发。

 

四.   报表开发

对于在团队中进行项目的开发时候为了考虑后期的维护和开发的完整性则需要引入公共的模板,主要介绍Library公共数据源以及样式模板和自定义javascript文件的导入:

首先定义公共数据源,在myeclipse中新建一个报表工程,new -> report web project, 建好工程之后可以看到report-viewer这个目录放置了birt运行时用户能够看到所有的jsp页面以及一些css样式和一些ajax相关的js文件等,如有需要可以根据个人兴趣自行修改样式(具体的修改会在后面做介绍),reports目录这个里面就是你所制作的报表了,其他的目录和web工程的目录是一样的,至于lib目录是个人建立的目录,里面放的是library的公共类库,用户可以在这个目录下新建一个library文件new -> library,建立好后双击打开,这里需要打开一个outline的面板window -> show view里面找到此面板打开(左边为工程目录,右边为outline中library的目录),如图:

            接下来就可以在Data Sources中建立链接数据库的数据源,点击鼠标右键新建New Data Sources,弹出的窗口选择第一个JDBC数据源设置好名字点击下一步,这里有Driver和jndi两种方式,通常会选择第一个进行数据库的配置,当然如果你已经在DB brower中已经配置好数据库的链接在这里就可以直接选择它。当然建立好数据源,同样的你也可以建立数据集和数据参数或者交叉表的cube。如果已经全部弄好接下来就可以进行开发一个简单的报表了。

 

1. 清单表

首先在reports目录中右键新建一张报表new -> reports,弹出窗口进行命名以及在哪一个目录下面,

点击下一步会出现一个template

下面就是公共的报表模板了,不过第一次做还是选择blank,点击下一步直接完成就会生成一张报表。

生成报表第一步还是建立数据源,因为我们之前已经在library中已经建立了数据源,此时我们就用那个作为报表开发的数据源,同样的在show view中打开library explorer窗口里面可以看到这个项目下的目录打开lib下面的library展开它,把数据源拖动到报表中的Data Source这样就会出现一个绑定的数据源,这样做的好处就是如果开发的报表数量较大,这样以后如果移植数据库只需要去修改library中的数据源,而其他的报表就会跟着自动都修改过来。

接下来我们就可以定义数据集了,在Data Sets中新建,命名好了就点击下一步,弹出来的窗口左边就会显示数据库的信息,所有的表都会在里面显示,而右边是你所写的sql,birt会根据你的sql生成相应的视图,点击下一步,可以看到这个窗口中的query就是你的sql和数据库信息,data Source就是数据源,Out Column会显示根据你的sql生成视图的信息包括输出字段、类型等,Computed Column就是计算列,这里可以手动给表添加一列,通过在aggregation中选择计算类型,expression中写出你定义的表达式,命名好之后就会在后面显示一列,parameter就是用来给报表绑定参数,filters是用来对报表进行数据过滤,在里面可以根据表达式对报表进行数据的过滤,Property binding中可以给写script代码,做各种业务逻辑的处理,下面的query timeout可以设置查询超时,preview是可以对数据进行预览,会显示sql生成视图的数据,如图:

    但我们定义好了数据集之后我们就可以把这个数据集手动直接拖到中间报表的layout的界面这样就会自动生成一个table表格,如果不做任何的样式处理就可以直接在下面的preview中直接预览报表,或者在上面的工具栏中有一个viewer report这里面有各种格式展示报表。同样的在数据集的下面会生成你sql所规定的字段,也可以单独拖动某一个字段到table中,对于后期如果有字段添加或者修改就可以用这种方式进行。

单纯的这样展现报表是不够的,可能会根据业务的需求,需要相应的参数给用户进行选择,例如文本框,下拉框之类的选择,报表会根据不同的参数来进行展现这样就会更为的直观了,接下来就进行参数的定义:

例如:select * from test where name=?这一段sql如果没有条件会查出所有的数据但是现在有了where条件,报表会根据这个条件查出数据,至于birt的规则规定凡是参数都设置为等于?,这样才能够识别它,接下来我们就在外面的Report parameters中定义参数,先定义最简单的文本框,同样还是新建会弹出窗口如图:

Name定义参数的名字会显示在report parameters中的名字,同样也会显示在报表运行时的参数名字,这里建议使用英文(后面会说明原因),下面会有prompt text这个就是可以替代name来定义中文名字例如:日期,这样既可以让用户看的直观也不会影响后期开发,Data Type为数据的类型,display type这里面可以定义参数的类型,包括文本框,下拉框,单选框,以及多选框,而右边的help text其实就是鼠标放在参数框的时候会出现你所定义的提示信息,下面则是格式的规定里面提供了一些校验,至于最后的4个复选框,其中包括该参数是否为必须填的参数和隐藏参数、不允许重复输入、可以进行多选的四种格式,同样的还可以给参数框提供一个默认的值,在里面可以根据业务需要在script中定义默认的参数,这样我们的文本框就定义好了。

如何将定义好的参数和报表关联起来,这个时候就需要关注之前有介绍到的数据集中的parameters点击新建在linked to report parameters连接到你所定义的参数,这样就完成了报表定义,sql中的where条件后的?就可以接收到了用户所输入的内容进行查询,(注意:?和参数的顺序必须一致,有多少个?就要有多少个参数)。

有时候根据业务需要,可能会根据某一个字段进行分组,这样显示起来就比较美观,点击detail行,右键insert group就会弹出分组的窗口设置,如图:

这里可以设置分组的名字,以及设置以那个字段作为分组条件,在下面的item Expression中可以设置这个组显示为那个字段,例如按照某个id来分组,但是显示的是相应的描述来给用户看更为的直观。

当我们插入分组后还需要一些调试可以看到在detail行上面增加了一个group行,我们只要把detail行的ind_dsc去掉就可以正常的显示分组后的数据了,但是birt的问题会出现某些先太粗之类的情况,这个需要你手动的针对粗的地方在border中把相应的边线只要去掉,多次测试后就可以正常显示了,

最后运行的样子:

2. 固定格子表

所谓固定格子就是一个方格一条数据的实现方式,这种方式的实现就不能用上面介绍的table来实现了,需要用到grid网格来进行操作,首先在show view中打开palette,这个里面提供了一些birt的控件,例如label,text等。这里我们将grid拖到报表中会弹出一个窗口选择几行几列,我们根据要求建好之后就可以开始制作了,我们可以从数据集的下拉框中找到所需要的数据把这些数据字段一个一个放置到自己所规定的位置中,可以在grid自由的定制表头,而数据就可以拖到相应表的位置进行展示,这样的报表没什么太大的难度就是根据表样来把字段拖到相应位置,如果定义表头可以插入label进行定义表头,这样很容易就完成了固定格子报表的展现。但是这种类型的报表的弊端就是开发起来的效率不是太好,尤其是字段过多的时候就会很慢,而且很容易出错。所以这种报表的出现率不是太高。

 

 

3. 交叉表

    这中报表形式是出现率比较大的形式,优点就是方便后台的维护,同时也相对很灵活。

和之前的表一样,定义数据源和数据集,之后在Data cube中新建一个交叉表的数据集,也就是把在data sets中定义好的拖到交叉表的相应的位置,Dataset中的Primary dataset定义需要的数据集在group and summery中定义交叉表的分组和明细,如图:

左边就是所有的数据集,右边就是你要展现交叉表定义的数据集,首先看groups这个就是创建分组,对应表中也就是表的左下角的位置,而下面的summary fields就是定义最终交叉表中展现的中间数据,也就是表中右下角位置,其实表中的右上角也可以放入分组的字段作为表的表头,将所有的数据集都拖放到交叉表中就可以把定义好的表拖到报表的制作页面了,可以直接将cube拉到展现页面中就可以生成,也可以在palette中把cross table拖到页面中,针对每个位置自己手动把在cube中定义的每个部分拖放到相应的位置,如图交叉表的空白结构:

交叉表拖放完字段的结构:

注意:如果在创建分组的时候,可能有些分组会有相应的子组,就可以把子组拖到父组的下面,不用在新的组了,例如:国家可能包含城市,城市包含地区等。

接下来还可以对行列添加分组小计和总计,当你点击左边的分组的 这个的时候会出来相应的选项,第一个就是显示和隐藏分组的,可以根据需要把不想显示的组前面的勾去掉就可以隐藏掉。第二个选项就是total这个里面可以添加行列的小计和合计,不过这里需要注意你的分组情况来勾选相应小计,最左侧的也就是最大分组级别,这样出来的就是所有组的合计会显示在最下面如果点击的是第二组级别那么出来的就是相应组的小计,如果需要给最右侧添加行的合计可以点击右上角的分组字段的total勾选相应的字段可以实现右侧的合计,如图:

最后就可以进行预览报表了。有的时候可能客户对于表中展现的数据有些顺序的要求,这样报表中只能按照升序或者降序的方式排列,无法满足,但是我们有方法可以实现就是在数据库中提前给那些需要排序的中文添加个id按照数字大小排列好,将id这个字段作为组放到交叉表中,把这个id字段拖到需要排序的字段的前面或者上面就可以限制他的顺序,正如上图中的org_id,左侧的org_id_type都是限定后面的汉字的顺序,不过需要注意的时候要隐藏这些id字段,在属性里面有个visibility中可以隐藏输出,选择all就可以了,但是还需要在advance中的box把相关的边框宽度都设置为0,因为默认是1,以及属性中的高度或者宽度都设置为0,就能实现了。

 

 

4. Chart图表

以线性图为例子,之前的定义是一样的,只是在报表页面要么在palette中把chart拖到右侧页面,要么在右侧页面鼠标右键有一个insert – chart就会弹出一个页面:

可以看出birt提供了多种图表的形式,开发者可以根据需求来选择相应的图表,这里我选择line线性图作为例子来说明,对于线性图提供了3种类型的样式,下面可以选择是2D还是3D,以及输出图片的格式,目前2.6支持四种格式的输出,同样还可以选择多个Y轴,

Flip axis其实就是x和y颠倒了,选择好之后就点击下一步

可以看到这个页面就是定义x和y需要显示的数据集,在select data中选择user data from 也就是之前外面定义好的数据集,分别在x轴和y轴定义自己需要的数据集中的字段,y轴可以定义多条曲线的也就是多个字段都可以展示,全部定义好了就可以下一步了,到format chart,这里就是对图表的界面样式进行设置,例如定义图表的标题,x和y轴的名字,颜色,字体,位置,大小以及各种事件的定义,如图:

Series中主要是定义图表点的连线的样式,以及Y轴左侧的数据的密度,可以自由设置从多少到多少,每个数据的间隔的倍数,可以使各种格式,百分号等等,也可以对每个线在interactivity中定义事件,包括onmouseover、onclick等多种事件处理,控制图标展示的效果

Chart Area可以定义X轴的一系列的属性,下面的Title、plot、legend都是对标题进行设置的,每条线的颜色对应的是什么含义都可以自己规定,还有图表的位置、标题的位置、大小等属性的设置。

 

五.   报表的参数使用

之前有介绍过文本框的使用,接下来在介绍下其他的三种参数的使用方法:

1. Combobox

下拉框,作为非常常用的一种控件,其他合文本框一样,区别就是他在select list value中选择静态变量或者动态变量:

所谓静态变量也就是自己手动去填入下拉框的内容在右侧点击new就可以对值进行输入,有相应的显示的值和实际的值,下侧也可以导入数据从已经定义的数据集中把数据导入进去,还可以对某一个值设置为默认的值,最下面还有Sort是可以进行排序的升序或者降序

所谓的动态变量就是通过读取数据库的数据来作为下拉框的值,在Data set可以选择数据集,select value选择值的字段,在display text中选择显示的内容,静态和动态的设置默认值的区别就是,动态可以写入script代码,灵活的控制默认值,而静态变量只能固定某一个值。

 

2. Radio Button

设置和其他参数是一样的,只是这个是类似于单选框的形式展现,例如男、女,在上面可以设置allow duplicate为多选,就形成了复选框的形式了,在这里他只能设置静态的变量也就是手动的输入参数的值。

 

 

3. List Box

该组件其实就是拉长了combobox形成了下拉的多选框,用户可以进行数据的多选这里也分为静态和动态,同样的也可以设置为多选的还是单选的,但是他和combobox的区别在于sql的构成形式,下拉框可以为name=?,但是该多选框只能是sql中的in(),括号中就是list box的值,如果想设置在数据集的参数中,就不能在parameters中来绑定参数了,需要在filters中点击新建

左边就是选择需要对那一个字段进行in的操作,中间呢顾名思义就选择in的操作符,而右边就选择

Category中的Report Parameters选择定义的那个list box参数,这样完成了多选框的定义。

 

 

六.   报表的级联参数的使用

所谓级联参数就是多个参数框,当用户选择第一个参数框中的某一个值的时候相应的第二个参数框就会根据第一个框中值到数据库查询出对应的数据,在开发过程中这种应用也是比较多的,接下来就以一个例子来说明级联的应用:

首先,定义一个数据集为年,其sql为:select year_id,year_name from dim_date

在定义一个月的数据集,其sql为:select mon_id,mon_name from dim_date a where year_id=? 这里的?其实就是来自于第一个年的值来查询出相应月份。

接下来就可以定义级联参数了,在report parameters中,新建一个cascading parameters group级联参数组如图:

同样的可以为参数组设置name和prompt text,下来可以定义single data set和multiple data set,因为我们要级联多个参数所以就选择后者了,在下面的参数框中点击add进行参数的添加,首先绑定年的数据集,下面的值设置year_id,默认值设置为year_name并取名为year,可以在下面的prompt text中设置中文名字作为显示方便用户看,至于数据类型和参数类型也可以设置自己需要的。在添加一个月的参数,和年的定义是一样的,设置mon_id和mon_name,此次两个级联的参数都定义完了,不过要怎么把两个参数关联在一起呢!也就是月中的where条件中的?需要来自年的值,接下来我们就在月的数据集中的paramenters中来关联年这个参数,如图:

这样我们的级联参数就定义完成了可以运行报表看看效果是不是实现了。

 

 

 

 

 

七.   模板及自定义js

1. 样式模板

有的时候我们开发的报表量过大为了统一报表的样式风格我们就需要公共的模板了

首先,在项目中new – template文件进行命名和目录的选择

下一步可以在这里面设置模板的名字和对这个模板的相关描述,还可以导入模板的图片。

模板建立好了之后其实就和一般的报表样式是一样的,在这个模板里面可以自己做一个通用样式的报表所有元素的定义和报表都是一样的,当我们做好之后模板是需要发布的才能够进行公共的使用,

右键点击模板会出现如图:

点击之后就可以填写发布模板的名字和描述等这样就完成了发布,至于如何使用在我们每次都新建报表的框里有个选择报表的样式的地方,在哪里就可以看到我们所定义的模板了,如果需要就选择模板进行报表的开发。

 

 

2. 自定义js文件

用户自己定义一个目录用来放置自己建立的js文件,接下来就新建一个javascript文件,右键new -> javascript如图:

点击完成就建立好了文件,我们就可以定义自己的方法了,这里我举一个简单的返回两个值相加的方法作为参考:

function combine(num1,num2){

   var str = num1 + “_”+ num2;

   return str;

}

写好方法之后就可以在报表中使用了,具体的使用方法如下:

打开你所要引入js文件的报表,切换到xml source的标签查看报表的配置源码,加入以下代码:

 

<list-property name="includeScripts">

   <property>js/test.js</property>

</list-property>

定义好了之后就可以在报表中进行测试,我在表中最后加入了一个动态文本

在script输入方法名字,传入了两个参数,最后预览报表的时候就会显示为:

我们可以看到最下面就会有输出1_2,这样就完成了自定义js功能。

但是需要注意的是有可能在chart中的事件script中无法引入自定义js文件,需要用户自己注意。

 

八.   报表中script的使用

1.在script中对sql的控制

这里我们介绍报表中如何使用script,首先举一个例子,还记得之前做报表都是将sql放在query中,在parameters中给报表绑定参数来完成的报表应用,其实还有一种方法我们可以把过长的sql进行拆分,一部分就放在script来实现追加sql同样的也可以达到目标,当我们的一些需求无法满足,就可以使用这种方法。

例如:我们在query中定义了一段sql,select * from test where name=?,我们可以将where之后的条件拆掉放到script中写,如图:

我们选中定义的数据集,在这个数据集的script中的beforeopen中可以添加相应代码,接下来我们可以通过使用var a = reportContext.getParameterValue(“参数名字”);这个方法可以获取用户所选择的参数,接下来我们就可以追加where之后的sql语句了,通过使用this.queryText += “ where name = ‘”+a+”’”;这里的a就是之前获取的动态参数值,这样就实现了该方法了。

同样的我们也可以在数据集中的prompt binding中定义this.queryText += “ where name = ‘”+a+”’”;个人还是比较偏向前者,因为前者很灵活,可以满足大量的参数应用,如果报表需要添加数据权限,同样可以在里面通过用session获取用户的id来控制登录用户所访问报表的权限,当然需要后台数据库的支持了。

这里给你大家提供一个小技巧,有的时候用户可能需要并不是所有的参数都是要填写的,所以一些参数就要设置为可填可不填的,这样我们在script中如何来控制呢?很简单,我们只要在追加sql那里稍微坐下if的判断例如:if(!"".equals(a) && a !=null){

   this.queryText += “ where name = ‘”+a+”’”;}

这样当用户输入了参数就会追加这段sql来限定查询结果,当然如果没有选择这段sql就不会追加了。

 

 

2.报表中script的控制

虽然birt提供了很多beforeopen、beforeclose等多种区域的script控制,其实用户可以理解字面意思,无非都是一些打开报表前就会运行或者关闭前所运行的代码等,用户可以根据需要来自行的控制。

⑴       .隔行换色

接下来我们来看看报表中的script应用,进入报表script

选中table的detail行,进入script,会有三种选择,onprepare,oncreate等,我以报表的隔行换色为例子来说明:

首先,我们在onprepare定义一个全局的变量count = 0;(不可以带var否则oncreate无法获取),在oncreate中写如下代码:

count++;

if(count%2 !=0){

style.setBackgroundColor("#F0F0F0");

}else{

style.setBackgroundColor("#FFFFCC");

}

这样我们就实现了报表的隔行换色的效果了。

还有另外一种的实现方法大体思路一样只是判断有区别,代码如下:

if(row.__rownum % 2 == 0){this.getStyle().backgroundColor = "#E9EAEB";}else{

this.getStyle().backgroundColor = "#FFFFFF";

}

 

⑵       .鼠标高亮

可以实现鼠标滑过表格数据会产生自己定义的背景颜色,

我们可以在表中的footer或者header行中任意插入一个text文本,选择html加入以下代码:(最好还是添加一个header行在里面加入文本代码)

<div id="d1"></div>

<script>   

    var o = document.getElementById("d1");

    while(o != null){

        if (o.tagName == "TBODY")

            break;

        o = o.parentNode;

    }

    for (var i = 1; i < o.children.length; i++) {

        var ro = o.children[i];

        ro.onmouseover = function(){this.style.background="#aaeeff";};

        ro.onmouseout = function(){  this.style.background="white";};

    }

</script>

效果图如下:

 

⑶       .birt所提供常用的script方法

①       .如何得到全局变量

首先,我们在报表中的initialize中定义一个全局变量代码如下:

reportContext.setPersistentGlobalVariable("testglobal", "test global string");

如果哪里需要用到这个变量我们就可以在相应的script中的onPrepare中输入this.text = reportContext.getPersistentGlobalVariable('testglobal');

那么text的原先的值就会被替代了。

 

 

②       .如何得到定义的集合全局变量

同样的写入appContext = reportContext.getAppContext();

           importPackage(Packages.java.util)

           myArrList = new ArrayList();

           myArrList.add("one");

           myArrList.add("two");

哪里需要就写入 appContext = reportContext.getAppContext();  myObject = appContext.get("AppContextTest");

                 this.text = myObject.size();

 

 

③       .如何得到定义的全局的方法

先定义方法 function gTest(v){

              return "Global Function:" + v;

           }

在需要的地方写this.text = gTest("MyTest");

 

 

④       .如何找到当页的最后一行

如果一页有40条数据,那么就在detail行中的onrender中写入if(this.getValue()%40==1){……}

 

 

⑤       .如何给某一条数据添加链接

在你需要添加的地方的onprepare中写入this.getAction().URI = "'http://www.google.com'";

 

 

⑥       .row中和cell中控制对象

Row:

if(this.getRowData().getExpressionValue("row[QtyOrdered]") > 30){

   this.getStyle().fontFamily = "Arial"

   this.getStyle().backgroundColor = "Yellow"

}

 

Cell:        this.getRowData().getExpressionValue("row.__rownum")==2

 

 

⑦       .动态文本中显示查询语句

文本名字为TestHeader,在beforeFactory中输入:

query = this.getDataSet("Data Set").queryText

this.getDynamicText("TestHeader").valueExpr = "query;";

 

 

⑧       .如何修改chart中的title

function beforeGeneration(chart,context){

   importPackage(Packages.org.eclipse.birt.chart.model.type.impl);

      newChartTitle = context.getExternalContext().getScriptable().getPersistentGlobalVariable("testglobal");   chart.getTitle().getLabel().getCaption().setValue(newChartTitle);

}

 

 

⑨       .方法集合

reportContext.getParameters(“参数名”):此方法获取用户输入的参数的值。

params[“参数名”]:也是获取用户输入的参数值,同上功能是一样的。

dataSetRow[“字段名”]:就是获取某一个字段的值,通常是在表格中双击detail中的字段就可以看到表达式。

row[“字段名”]:这个就是可以在script中获取某一个字段的数据。

this.getValue():此方法也是获取字段的数据,不过他是依赖于你写在哪一个字段的script中的。

getStyle():这个方法获取某个字段的样式对象,别且里面提供大量修改样式方法,例如字体大小、位置、颜色、背景色等。

this.helpText:也就是鼠标滑过显示的提示信息。

this.horizontalPosition:水平位置可以居中、居左、居右。

this.verticalPosition:垂直位置可以居中、居顶、局底。

this.name:设置其name属性。

this.height和this.width:设置宽度和高度。

this.getHyperlink:获取钻取的超链接对象。

setDisplayValue():设置默认的名字。

this.getParent().getParent().getParent():顺序就为dataElement->Cell->Row->Table

 

 

⑩       .输出sql和日志调试报表

输出sql:

importPackage( Packages.java.io );  

out = new PrintWriter( new FileWriter("f:/debuginfo.txt", true ) );  

out.println("sql="+this.queryText);  

out.close();

 

输出日志查看信息:

在script中的initialize:

mxReportScriptContext.setDefaultLogLevel("DEBUG");

mxReportScriptContext.setDefaultLogFile("c:/temp/prprint.log");

 

 

 

九.   项目开发中整合birt

首先介绍开发中整合的环境,最为常用应该就是SSH和birt的整合,但是在项目开发中一般会把系统的项目和birt的项目分开放在服务器上,无论是用什么技术,系统的项目中只要在规定的地方添加一个链接就可以调用birt项目中的报表了。

   这里我以经历的项目为例做说明,我们的系统采用的是java的SSH和页面的ext、flex整合开发的系统,而另一个则是birt的项目,页面上则用ext中tab把birt的报表页面嵌进去相当于浏览器的页面一样,只需要配置birt报表的链接地址就可以了如图:

当然如果采用的传统的jsp的页面技术,可以选择iframe形式把报表页面嵌进去。

⑴  .struts2整合问题

如果用户采用的是struts2框架来进行开发在和birt整合时候肯定会出现404找不到报表的错误提示,为什么会出现这个问题其实是和birt机制有关系,因为birt的转发请求的机制是基于servlet的请求,而struts2的转发请求时候会根据自己的核心控制器来控制请求,也就是会把不属于自己的范畴的请求全部过滤掉,所以报表的servlet请求就没法找到相应的报表了。

针对这个问题我们是有处理的办法,就是自己为birt写一个专门控制请求的类,这个可以让请求避开struts2的拦截,具体代码如下:

package util;

import java.io.IOException;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.RequestDispatcher;

import javax.servlet.ServletContext;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

public class BirtFilter implements Filter{

   //用来封装birt相关功能的uri和所对应的Servlet名键值对

   Map<String,String> map = new HashMap<String,String>();

   ServletContext context;

   //debug开关

   static boolean debug = false;

   public void destroy() {

      map = null;

   }

    /**

     * 过滤birt请求,转发到对应的servlet,以绕过其他的过滤器,struts2

     *

     */

   public void doFilter(ServletRequest request, ServletResponse response,

        FilterChain chain) throws IOException, ServletException {

      HttpServletRequest req = (HttpServletRequest) request;

      String uri = req.getRequestURI();

      if(debug){

         System.out.println(">>>Requesting " + uri + "?" + req.getQueryString());

      }

      Set<String> keys = map.keySet();

      for(String key : keys){

        if(uri.contains(key)){

           RequestDispatcher rd = this.context.getNamedDispatcher(map.get(key));

           if(rd != null){

             if(debug){

               System.out.println(">>>Redirect successfully executed");

             }

             //跳过其他的过滤器

             rd.forward(request,response);

           }else{

                if(debug){

                 System.out.println(">>>Redirect unsuccessfully executed");

                }

           }

           return;

        }

      }

      chain.doFilter(request, response);

   }

 

   public void init(FilterConfig filterConfig) throws ServletException {

      this.context = filterConfig.getServletContext();

      map.put("frameset", "ViewerServlet");

       map.put("preview", "EngineServlet");

   }

}

写好以上代码接下来我们就要在web.xml中来配置这个过滤器了代码如下:

<filter>

        <filter-name>BirtFilter</filter-name>

        <filter-class>util.BirtFilter</filter-class>

</filter>

<filter-mapping>

        <filter-name>BirtFilter</filter-name>

        <url-pattern>/*</url-pattern>

</filter-mapping>

注意以上代码一定要配置在struts2的过滤器之前!!!

 

⑵  .实现报表的数据权限的控制

   权限一般分为两种,报表权限和数据权限。前者其实就是能不能让用户看到这张报表,这种属于系统来进行是否显示的控制。后者则是在报表中这个用户能够看到多少数据的权限控制。在开发中这两种是最为常用的方式,也是必须的。这里我们主要介绍后者,因为前者属于系统的控制和报表没什么关系。

当然数据权限的控制主要工作还是集中于数据库,首先用户登录都会有他的登录账号,而数据库中则是通过账号来控制这个用户能看到那些数据,例如这个用户只能看自己部门的数据,那么就在相应的表中的部门内的数据中加入这个用户的账号,通过这个账号就可以关联到这个部门的数据了,后台数据准备好了之后,我们就先从系统触发,对于两个项目来说我们可以通过session的方式来进行传递用户的账号,只是这里还会出现一个问题,就是两个独立的项目是不能共用一个session的,不过不用担心还是有办法可以解决的,第一种就是你可以把session持久化到数据库,只不过每次用完都需要删除数据库的数据。这里我主要介绍第二种通过常用的session方式来进行传递。

首先,在系统中我们需要写下把用户账号放入到session的代码,按照传统的方法直接就可以获取session在往session放入账号值就正常使用,这里我们需要特殊处理,起初我是采用ServletContext,但是经过测试发现ServletContext对于该域内就仅有这一个,所以就会出现后面的会把之前的覆盖掉,所以我们还需要再做一些功夫,于是我在这个基础上就引入了cookie,以唯一的sessionID为名来控制session传递过去的唯一性,代码如下:

ServletContext context = getRequest().getSession().getServletContext().getContext("/PrimeTPA");

               HashMap s_map = (HashMap)context.getAttribute("session_MAP");

               String session_id = getSession().getId();

                getSession().setAttribute("userId",user.getUserId());

               if(s_map == null){

                  s_map = new HashMap();

               }

               s_map.put(session_id,getSession());

               context.setAttribute("session_MAP",s_map);

               Cookie cookie = new Cookie("sessionID",getSession().getId());

               cookie.setMaxAge(-1);

               cookie.setPath("/PrimeTPA_Report");

               getResponse().addCookie(cookie);

 

此处的request、session、response、这些用户单独自己封装方法去获取这些对象,还有在getContext(“/PrimeTPA”)这个里面需要写你的系统项目的名称,也就是在报表项目也要通过这个方法获取这个项目中的context,其实就是为了设置域中那些项目共用这个context,有了以上代码我们就可以在报表中获取session中的内容了代码如下:

importPackage(Packages.javax.servlet.http);

var get_sessionID = "";

var cookieName = "sessionID";

var context = reportContext.getHttpServletRequest().getSession().getServletContext().getContext("/PrimeTPA");

var session = reportContext.getHttpServletRequest().getSession();

var cookies = reportContext.getHttpServletRequest().getRequest().getCookies();

for(var i=0;i<cookies.length;i++){

    if(cookies[i].getName().equals(cookieName)){

       get_sessionID = cookies[i].getValue();

    }

}

var hashMap = context.getAttribute("session_MAP");

if(hashMap == null){

    hashMap = new HashMap();

}

var hash_session = hashMap.get(get_sessionID);

var user = hash_session.getAttribute("userId");

 

userId是用户自己定义的session的键名字,这里我们就可以获取用户的登录的账号了,但是还少一步工作就是我们还需要在服务器中区配置一些信息,也就是之前提到过的如何识别那些项目共用这个context呢!我以tomcat为例,代码如下:

<Host name="localhost"  appBase="webapps"

            unpackWARs="true" autoDeploy="true"

            xmlValidation="false" xmlNamespaceAware="false">

        <Context path="/PrimeTPA"  debug="0" reloadable="true" crossContext="true"></Context>

           <Context path="/PrimeTPA_Report"  debug="0" reloadable="true" crossContext="true"></Context>

</Host>

当我们配置好了之后就ok正常运行了。

 

 

 

 

十.   Birt的扩展

很多时候我们会去和一些付费的工具做一些比较,其实不仅仅只是功能的差别,样式上也有很大的差别,为了满足客户的需求我们就得自己去对birt的页面或者功能进行扩展。

1.birt的页面样式

birt的页面样式基本都提供给我们了,就在项目中的report-viewer中的birt目录下,里面包括了所有的jsp和css以及js文件,首先给大家看看我自己修改的页面样式;

当然可能不一定是最好看的,起码要比最原始的页面要好很多了,这里主要需要修改的地方就是birt-page-parameters,这个里面包含了所有的参数选择页面,我们都知道birt提供的下拉框下面会带个文本框,当参数不是必须的时候又会有个null value,看起来不太美观。

(1).修改combobox

CSS样式代码:

<style type="text/css">

           select{

                  border-right: #000000 1px solid;

                  border-top: #ffffff 1px solid;

                  font-size: 14px;

                  border-left: #ffffff 1px solid;

                  color:#003366;

                  border-bottom: #000000 1px solid;

                  background-color:ECE9D8;

                  }

</style>

 

接着就是tr中的代码,这里大家自己去对比不同的地方

<TR>

    <TD NOWRAP><FONT TITLE="<%= parameterBean.getToolTip( ) %>"><LABEL FOR="<%= encodedParameterName + "_selection"%>"><%= parameterBean.getDisplayName( ) %>:</LABEL></FONT>

       <%-- is required --%>

       <%

       if ( parameterBean.isRequired( ) )

       {

       %>

           <FONT COLOR="red"><LABEL FOR="<%= encodedParameterName + "_selection"%>">*</LABEL></FONT>

       <%

       }

       %></TD>

    <TD NOWRAP WIDTH="100%">

       <INPUT TYPE="HIDDEN" ID="control_type" VALUE="select">

       <INPUT TYPE="HIDDEN" ID="data_type" VALUE="<%="" + parameterBean.getParameter( ).getDataType( ) %>">

       <INPUT TYPE="HIDDEN"

           ID="<%= encodedParameterName + "_value" %>"

           NAME="<%= encodedParameterName %>"

           <%= paramValue != null ? " VALUE=\"" + ParameterAccessor.htmlEncode( paramValue ) + "\"": "" %>

       >

 

<% 

    boolean CHECKED = true;

      

    if ( parameterBean.allowNewValues( ) ) // TODO: Editable

    {

       CHECKED = parameterBean.isValueInList( )

                || paramValue == null

                || ( !parameterBean.isValueInList( ) && defaultValue != null && defaultValue.equals( paramValue ) );     

   

    }

%>

       <SELECT class="select" style="width:250px;" ID="<%= encodedParameterName + "_selection"%>"

           TITLE="<%= parameterBean.getToolTip( ) %>"

           <%= !CHECKED ? "DISABLED='true'" : "" %>

           <%=  allowMultiValue? "multiple='true'" : "" %>

           <%= ( !parameterBean.allowNewValues( ) && parameterBean.isRequired( ) ) ? "aria-required='true'" : "" %>

           >

<%

    if ( parameterBean.getSelectionList( ) != null )

    {

       if( !parameterBean.isRequired( ) || ( parameterBean.isCascade( ) && DataUtil.trimString( defaultValue ).length( )<=0 ) )

       {

           if( allowMultiValue && DataUtil.contain( values,"",true ) )

           {

%>

       <OPTION SELECTED></OPTION>

<%           

           }

           else

           {

%>

       <OPTION>请选择</OPTION>

<%

           }

       }

      

       if ( DataUtil.trimString( defaultValue ).length( ) > 0 && !parameterBean.isDefaultValueInList( ) ) // Add default value in Combo Box

       {

           boolean flag = false;

           if( allowMultiValue )

           {

              flag = DataUtil.contain( values, defaultValue, true );

           }

           else

           {

              flag = CHECKED && !parameterBean.isValueInList( );

              // if displayText is in request, use it

              if( flag && parameterBean.isDisplayTextInReq( ) )

              {

                  defaultDisplayText = displayText;

              }            

           }

%>

           <OPTION VALUE="<%= ParameterAccessor.htmlEncode( defaultValue ) %>"

                   TITLE="<%= ParameterAccessor.htmlEncode( defaultDisplayText ) %>"

              <%=  flag ? "SELECTED" : "" %> > <%= ParameterAccessor.htmlEncode( defaultDisplayText ) %></OPTION>

<% 

       }

      

       boolean isSelected = false;

       for ( int i = 0; i < parameterBean.getSelectionList( ).size( ); i++ )

       {

           ParameterSelectionChoice selectionItem = ( ParameterSelectionChoice )parameterBean.getSelectionList( ).get( i );                   

           String label = selectionItem.getLabel( );

           String value = ( String ) selectionItem.getValue( );

           String outputValue = ParameterAccessor.htmlEncode(( value == null)?IBirtConstants.NULL_VALUE:value);

           String outputLabel = ParameterAccessor.htmlEncode(( label == null)?IBirtConstants.NULL_VALUE_DISPLAY:label);

 

           if( allowMultiValue )

           {

              if( DataUtil.contain( values, value, true ) )

              {

%>

           <OPTION VALUE="<%= outputValue %>"

                   TITLE="<%= outputLabel %>"

                   SELECTED><%= outputLabel %></OPTION>

<%

                 

              }

              else

              {

%>

           <OPTION VALUE="<%= outputValue %>"

                   TITLE="<%= outputLabel %>"><%= outputLabel %></OPTION>

<%               

              }

           }

           else

           {

              if ( !isSelected && DataUtil.equals( paramValue, value )

                   && ( !isDisplayTextInList || ( isDisplayTextInList && DataUtil.equals(label, displayText ) )))

              {

                  isSelected = true;            

%>

           <OPTION VALUE="<%= outputValue %>"

                   TITLE="<%= outputLabel %>"

                   SELECTED><%= outputLabel %></OPTION>

<%

              }

              else

              {

%>

           <OPTION VALUE="<%= outputValue %>"

                   TITLE="<%= outputLabel %>"><%= outputLabel %></OPTION>

<%

              }

           }

       }

    }

%>

       </SELECT>

<%

    if ( parameterBean.allowNewValues( ) ) // TODO: editable.

    {

%>

       <BR>

       <LABEL FOR="<%= encodedParameterName + "_radio_input" %>" CLASS="birtviewer_hidden_label">Input</LABEL>

      

       <LABEL FOR="<%= encodedParameterName + "_input" %>" CLASS="birtviewer_hidden_label">Input text</LABEL>

      

       <INPUT TYPE="HIDDEN"

           ID="<%= encodedParameterName + "_displayText" %>"

           <%= !CHECKED && displayText != null ? "VALUE=\"" + ParameterAccessor.htmlEncode( displayText ) + "\"": "" %>

           >     

    <%

      }

    %>

       <INPUT TYPE="HIDDEN" ID="isRequired"

           VALUE = "<%= parameterBean.isRequired( )? "true": "false" %>">

          

    <%

    if ( parameterBean.isCascade( ) )

    {

    %>

       <INPUT TYPE="HIDDEN" ID="<%=IBirtConstants.IS_CASCADE%>" VALUE="true"/>

    <%

    }

    %>

    </TD>

</TR>

 

 

(2).修改textbox页面

<TR>

   <TD NOWRAP>

      <FONT TITLE="<%= parameterBean.getToolTip( ) %>"><LABEL FOR="<%= encodedParameterName %>"><%= parameterBean.getDisplayName( ) %>:</LABEL></FONT>

      <%-- is required --%>

      <%

      if ( parameterBean.isRequired( ) )

      {

      %>

        <FONT COLOR="red"><LABEL FOR="<%= encodedParameterName %>">*</LABEL></FONT>

      <%

      }

      %>

   </TD>

   <TD NOWRAP WIDTH="100%">

   <INPUT TYPE="HIDDEN" ID="control_type" VALUE="text">

   <INPUT TYPE="HIDDEN" ID="data_type" VALUE="<%="" + parameterBean.getParameter( ).getDataType( ) %>">

<%

   if ( !parameterBean.isRequired( ) )

   {

%>

      <LABEL FOR="<%= encodedParameterName + "_radio_notnull" %>" CLASS="birtviewer_hidden_label">Input text</LABEL>

<%

   }

%>

   <%

      if(parameterBean.getName().equals("年月日")||parameterBean.getName().equals("日期")||parameterBean.getName().equals("time")||parameterBean.getName().equals("date")||parameterBean.getName().equals("date_id")||parameterBean.getName().equals("date_dte")||parameterBean.getName().equals("date_dt"))

      {

   %>

      <INPUT CLASS="BirtViewer_parameter_dialog_Input"

        TYPE="<%= parameterBean.isValueConcealed( )? "PASSWORD" : "TEXT" %>"

        NAME="<%= encodedParameterName %>"

        ID="<%= encodedParameterName %>"

        TITLE="<%= parameterBean.getToolTip( ) %>"

        VALUE="<%= ParameterAccessor.htmlEncode( ( parameterBean.getDisplayText( ) ==null )? "" : parameterBean.getDisplayText( ) ) %>"

        <%= ( !parameterBean.isRequired( ) && parameterBean.getValue( ) == null )? "CHECKED" : "" %>

        <%= parameterBean.isRequired( ) ? "aria-required='true'" : "" %>

            onclick="setday(this)" style="background:url(../images/date.png) no-repeat right"

            >

    <%

      }else{

   %>    

      <INPUT CLASS="BirtViewer_parameter_dialog_Input"

        TYPE="<%= parameterBean.isValueConcealed( )? "PASSWORD" : "TEXT" %>"

        NAME="<%= encodedParameterName %>"

        ID="<%= encodedParameterName %>"

        TITLE="<%= parameterBean.getToolTip( ) %>"

        VALUE="<%= ParameterAccessor.htmlEncode( ( parameterBean.getDisplayText( ) ==null )? "" : parameterBean.getDisplayText( ) ) %>"

        <%= ( !parameterBean.isRequired( ) && parameterBean.getValue( ) == null )? "CHECKED" : "" %>

        <%= parameterBean.isRequired( ) ? "aria-required='true'" : "" %>

            >

   <%

       }

   %>

      <INPUT TYPE="HIDDEN"

        ID="<%= encodedParameterName + "_value" %>"

        VALUE="<%= ParameterAccessor.htmlEncode( ( parameterBean.getValue( ) ==null )? "" : parameterBean.getValue( ) ) %>"

        >

     

      <INPUT TYPE="HIDDEN"

        ID="<%= encodedParameterName + "_displayText" %>"

        VALUE="<%= ParameterAccessor.htmlEncode( ( parameterBean.getDisplayText( ) ==null )? "" : parameterBean.getDisplayText( ) ) %>"

        >

     

<%

   if ( !parameterBean.isRequired( ) )

   {

%>

      <BR>

      <LABEL FOR="<%= encodedParameterName + "_radio_null" %>" CLASS="birtviewer_hidden_label">Null Value</LABEL>

<%

   }

%>

      <INPUT TYPE="HIDDEN" ID="isRequired"

        VALUE = "<%= parameterBean.isRequired( )? "true": "false" %>">

   </TD>

</TR>

至于其他的参数页面用户根据以上的例子参照着修改,实现自己想要的页面的样式。

 

 

(3).按钮样式的修改

在dialog的目录下dialogfragment的页面中最下面就是可以设置按钮的样式,代码如下:

<DIV id="birt_hint" style="font-size:12px;color:#000000;display:none;position:absolute; z-index:300;background-color:#F7F7F7; layer-background-color: #0099FF; border: 1px #000000 solid;filter:Alpha(style=0,opacity=80,finishOpacity=100);">

</DIV>

 

 

 

2.birt国际化

Birt默认的是英文的,对于用户看很不方便,所以我们需要给他做国际化,不过目前有提供下载汉化包的地方,用户也可以下载汉化包安装插件到你的开发环境,在这里给大家介绍如何自己修改birt的源文件来实现国际化。

首先找到viewservlet的jar文件,到最下层的目录找到resource这个目录进去后打开Messages.properties文件这个里面是birt关于页面展示的大部分的文字配置文件,我们可以看到每个后面都是赋值有英文,这里需要我们给他改成中文,直接改是不行的需要引入转换ascii码的工具,不过系统都是有自带的,我们直接在window中运行native2ascii这样就进入了这个工具可以进行编码了,然后我们只要在这个里面输入汉字,回车后就会显示相应的ascii的编码把这个编码换到等号的后面就ok了。

 

以下是修改过的配置文件了,用户可以根据情况来自行的定义

 

 

 

十一.     Birt的使用小技巧

首先先介绍下钻取的实现方法,所谓钻取就是从一张表通过某一个字段链接到另一张报表来进行数据分析,例如:做好两张报表之后,我们从第一张表出发:

当我们点击本日的时候就会钻取到本日下的明细报表,所以选定本日在下面的属性表Properties里面有个超链接Hyperlink,点击编辑edit会弹出设置框:

这里我们选择drill-through是钻取,在step1中选择要钻取到的报表,在report parameters设置需要给第二张报表传递的参数,这里显示的参数其实是第二张报表所建立的参数,假如你在第二张报表建立了日期、部门参数,那么在这里就要给这两个参数设置值这样才能正常的传递到第二张表,参数设置好了之后到step4来选择窗口展现的形式,是打开新的窗口还是在同一个窗口显示根据用户的自己的需要,至于中间的选项暂时用不到,step6可以设置鼠标提示信息。

1. 报表返回

birt本身没有提供现成的返回操作,之前个人有用过添加一个text在里面写入javascript的后退功能,go、back等方法,但是发现效果不是很好,因为第一次进行的是带有参数的提交浏览器会弹出重试或取消的窗口,很不友好。于是我就想了钻取到第二张表那么也可以在第二张表钻取回第一张表,需要注意的就是我们必须要在第二张表建立和第一张表一样的参数,至少第一张有的都必须建立,是为了保证把第一张表的参数全部都传个第二张,当我们要返回的时候只需要把之前传过来的参数在传递回去就可以实现了返回的操作

在表上面添加了一个label给这个label添加了钻取功能,和之前设置参数的方式一样,只要把传递过来的参数都在返回去就实现了此功能,但是需要注意的是第二张表建立第一张表的参数的时候,要把这些参数都设置为不必要填写的参数并隐藏起来,因为这些和第二张表运行时无关的参数只是为了返回时能满足一表的需求。

 

 

2. 报表参数的默认值

尤其是用户选择日期,可能会有年月日的下拉框或者文本框的形式出现,为了方便用户的操作我们最好能够提供给用户一个默认值,这样就不需要手动的在去选择,除非需要查询别的日期。这里分为日报和月报:

⑴.首先,日报根据业务习惯通常会默认系统时间的前一天,那么我们一般来说这种情况会用文本框来实现,让用户输入一个8位日期,在文本框的script中我们可以输入以下代码:

if(BirtDateTime.month(new Date())<10 && BirtDateTime.month(new Date())>1){

    var a = (new Date().getMonth()).toString();

    var b = "0"+a;

    var c = "0"+BirtDateTime.month(new Date()).toString();

}else if(BirtDateTime.month(new Date())>10 && BirtDateTime.month(new Date())<13){

    var a = (new Date().getMonth()).toString();

    var b = a;

    var c = BirtDateTime.month(new Date()).toString();

}else if(BirtDateTime.month(new Date()) == 10){

    var a = "09";

    var b = a;

    var c = "10";

}else if(BirtDateTime.month(new Date()) == 1){

    var a = "12";

    var b = a;

    var c = "01";

}

 

if(new Date().getDate()<10 && new Date().getDate()>1){

    var d = "0"+(new Date().getDate() - 1).toString();

    var e = "0"+new Date().getDate().toString();

}else if(new Date().getDate()>10 && new Date().getDate()<32){

    var d = (new Date().getDate() - 1).toString();

    var e = new Date().getDate().toString();

}else if(new Date().getDate()==10){

    var d  = "09";

    var e = "10";

}

if(new Date().getDate()==1){

    if(a.equals("1")||a.equals("3")||a.equals("5")||a.equals("7")||a.equals("8")||a.equals("10")||a.equals("12")){

       BirtDateTime.year(new Date()).toString()+b+"31"

    }

    if(a.equals("2")){

           if(new Date().getFullYear() % 4 !=0){

              BirtDateTime.year(new Date()).toString()+b+"28" 

           }else{

              BirtDateTime.year(new Date()).toString()+b+"29"

           }

    }else{

           BirtDateTime.year(new Date()).toString()+b+"30"

    }

}else{

    BirtDateTime.year(new Date()).toString()+c+d

}

 

if(BirtDateTime.month(new Date())==1&&new Date().getDate()==1){

    (BirtDateTime.year(new Date())-1).toString()+"1231"

}

 

 

(2).其次是月报,月报一般会返回上月末的日期,在这里我们只用给用一个年和月的下拉框的选择,至于日我们在script中自己去拼,因此年的下拉框为:

if(BirtDateTime.month(new Date()) == 1){

(BirtDateTime.year(new Date())-1).toString()

}else{

BirtDateTime.year(new Date()).toString()

}

月的下拉框为:

if(BirtDateTime.month(new Date()) == 1){

"12"

}

if(BirtDateTime.month(new Date())>1&&BirtDateTime.month(new Date())<11){

"0"+(BirtDateTime.month(new Date())-1).toString()

}

if(BirtDateTime.month(new Date()) == 11){

"10"

}

if(BirtDateTime.month(new Date()) == 12){

"11"

}

 

在script中我们可以写入以下代码控制日:

var g = reportContext.getParameterValue("yer");

var h = reportContext.getParameterValue("mon");

if(h.equals("01")||h.equals("03")||h.equals("05")||h.equals("07")||h.equals("08")||h.equals("10")||h.equals("12")){

   var i = g+h+"31";

   this.queryText += " ";

}

if(h.equals("04")||h.equals("06")||h.equals("09")||h.equals("11")){

   var i = g+h+"30";

   this.queryText += " ";

}

if(h.equals("02")){

   if(g.equals("2012")||g.equals("2016")||g.equals("2020")||g.equals("2024")||g.equals("2028")){

      var i = g+h+"29";

      this.queryText += " ";

   }else{

      var i = g+h+"28";

      this.queryText += " ";

   }

}

此处的js代码写的比较差(当然了,这只是个示例而已,使用者根据具体情况可优化。)

 

 

3. 报表web.xml配置问题

曾经遇到过相应的问题就是当报表重新选择参数的时候里面的数据并没有变化,其实这是因为报表并没有重新的加载运行而是一直运行缓存的东西,所以我们需要在web.xml配置相应代码强制报表每次运行都要重新的加载,代码如下:

 

<context-param>

    <description>Flag whether to force browser-optimized HTML output. Defaults to true</description>

    <param-name>BIRT_OVERWRITE_DOCUMENT</param-name>

    <param-value>true</param-value>

</context-param>

 

 

4. 参数页面的开发

有些人会认为birt的参数页面不美观,而且对于多选框的实现方式用户操作起来也很不方便,所以就会有了自己想要开发参数页面的想法,这里先给大家看看我个人开发的页面样式:

这个是采用ext技术开发,相对于传统的jsp要好看很多,而且对于多选框的操作会更为的方便。

 

 

(1).参数的传递方式

Birt提供的接受参数的方式有三种,前两种都是通过url的形式来接收,第二种可以从session中获取参数。

第一种:url为

http://localhost:8080/birt-web/frameset?__report=test.rptdesign&sample=my+parameter

sample就是要给报表传递的参数,那么在报表中只要设置了和这个名字一样的参数就可以接收到这个值来运行报表了。

之前还有说过如果在script中用方法来获取参数params[“sample”],这样就无需在定义参数就可以运行报表了。

 

第二种:session

其实就是把准备好的参数通过session的形式传给报表,在报表中的script中beforeOpen中写

var session =reportContext.getHttpServletRequest().getSession();

user = session.getAttribute("user");

这样就可以把user的值拼到sql语句的条件中进行查询了。

 

 

(2).birt标签的使用

Birt的标签是放在/WEB-INF/report-engine/tlds/birt.tld

①  .view标签

示例:
<birt:viewer  id="1"
             pattern="run"    
             reportDesign="test1.rptdesign"
             position="absolute"
             width="800"
             height="500"
             left="50"
             top="50"
             format="html"
             svg="false">
    <birt:param name="sample" value="abc"/>
    <birt:param name="Cust" value="<%=110%>"/>        
</birt:viewer>

id:必须指定,
pattern: 不一定 要指定,指定运行使用的servlet, 默认为frameset
reportDesign:指定报表文件名
title :可选,指定报表的标题,其实这不是设计报表的标题,而是报表运行时显示在报表上面的标题。
isHostPage:可选,默认为false,指定报表是否全屏显示,此属性设置,则width,height,scrolling 属性作废。
scrolling :可选,是否出现滚动条
position: 可选,报表相对于页面的位置,值为static | absolute | fixed | relative,如果设置了isHostPage,该属性作废。
style : 可选,报表显示的样式,没多说的。,如果设置了isHostPage,该属性作废
width,heigth,top,left: 分别设置报表显示的宽,高,上边距,左边距
frameborder :可选,设置报表所在的iframe是否显示边框,默认不显示。值为yes/no
reportDocument : 可选,指定报表文档,只支持file:url,这样的格式。
reportlet : 可选,使用reportDocument ,可指定这个属性,只是指定reportlet 实例的id, 另frameset不支持此属性。
bookmark : 可选,指定目标书签名称
locale : 指定Locale信息,指定语言环境
svg : 可选,指定是否支持输出svg格式文档。
format : 可选,指定报表的输出格式
pageOverflow : 可选,当输出格式为pdf时,指定页面溢出样式,0 表示自动,1表示实际大小,2表示适合页面的大小
pageNum: 可选,指定是否显示页码
pageRange:  指定页面范围。当运行文档文件时指定这个属性。
resourceFolder : 指定相关的资源文件,默认识别web.xml定义的资源文件夹。
showTitle: 是否显示报表标题,默认为true
showToolBar: 是否显示工具条,默认为true
showNavigationBar: 是否显示导航条,默认为true,但是如果allowPageBreak设置为false,该属性作废。
showParameterPage: 是否显示参数对话框。默认为true,

 

 

②  .report标签

和view标签差不多,但是report没有使用ajax支持,而是直接将内容显示在页面。 内部应该使用了preview。
另有一个特别的属性reportContainer,有两个可选值,iframe,和div,默认为iframe. 指定使用report的容器。
其他属性和view都差不多,我就不说了。给个示例:

<birt:report id="2"
             reportDesign="test.rptdesign"
             position="absolute"
             width="400"
             height="300"
             left="900"
             top="100"
             format="pdf"
             reportContainer="iframe">
    <birt:param name="sample" value="abc"/>        
</birt:report>  

 

 

 

③  .param标签

报表参数相关的标签。
name: 指定报表参数名称
value; 参数值
pattern: 参数格式
displayText: 显示文字
isLocale: 指定参数是否本地化字符

 

 

④  . parameterPage标签

配置参数页面。
id : 必选。指定参数页面的id
name : 指定参数页面name,如果isCustom设置为true,则此属性一定要写,且唯一。
isCustom : 指定是否使用用户自定义参数页面。默认为false;
target : 指定请求打开窗口的位置。
其他属性与view相似,这里也不说了。
给个例子:
<birt:parameterPage id="parameterPage"
                pattern="run"
                reportDesign="test.rptdesign"
                target="myiframe"
                width="600"
                height="400"
                format="html"/>

<iframe name="myiframe" width="600" height="400"></iframe>

 

⑤  . paramDef 标签

这个标签用来生成参数参数页面定义的参数的html代码。
有以下几个属性
id,name,value,pattern,displayText,isLocale,title,style,cssClass.
这样说可能大家还是不懂,
给个例子就明白怎么回事了

<birt:parameterPage
        id="report2"
        name="page2"
        reportDesign="test.rptdesign"
        isCustom="true"                  //指定自定义页面
        pattern="frameset">
        id: <birt:paramDef id="id" name="id" title="这是设置id的区域"/>        
        <br><br>        
        
        sex: <birt:paramDef id="sex" name="sex"/>
        <br><br>        
        <input type="submit" name="submit" value="Sumbit form"/>
        <br><br>

</birt:parameterPage>

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页