很多使用过熟悉web报表工具的人都会发现,国内主流的报表工具FineReport 不延迟报表展示 不延迟报表展示是指:在有自定义参数的情况下,报表的结果展示不需要用户手动点击查询按钮,自动使用参数的默认值进行第一次查询并输出结果。 打开之前所做的模板:%FR_HOME%\WebReport\WEB-INF\reportlets\doc\Tutorial\Parameter\paratype1.cpt 1.参数设计界面 不选中延迟报表展示复选框,如下图 ![]() 2.设置参数默认值 打开报表|报表参数,将参数classno默认值设为Class1,如下图 ![]() 将参数classno拖入相应控件单元格,参数界面上也将显示出默认值。 ![]() 3.点击分页预览 可以看到,预览结果为 ![]() 此时用户没有选择classno的值,也没有点击查询按钮,自动使用参数classno的默认值Class1进行了第一次查询,这就是不延迟报表展示。 将此模板保存为: %FR_HOME%\WebReport\WEB-INF\reportlets\doc\Tutorial\Parameter\paratype6.cpt 参数控件动态显示 由于业务的需要,很多情况下需要当满足某个条件时,某些查询条件才显示出来,此时参数控件就需要动态的控制其是否可见。 //通过控件的visible()、invisible()属性控制其可视、不可视 var [Widget] = form.getWidgetByName("[ParaName]"); //通过控件名获取控件 [Widget].visible(); //设置该控件可见 [Widget].invisible(); //设置该控件不可见 实例: 该实例实现效果:当选择日报时,右侧出现一个日期查询控件,选择月报时,则让用户选择年月,例如2008年3月,选择年报时,即让用户选择年份。 1. 模板设计 1.1 新建报表 1.2 添加数据源 新建一个名为ds1的数据库查询,SQL语句: SELECT equipment,amount,costs,updatetime,equipmentId FROM EquipmentDetail where 1=1 ${if(type='日报'," and format(updatetime,'yyyy-mm-dd') = '" + date + "'","")} ${if(type='月报'," and month(updatetime) = "+ month + " and year(updatetime) = " + year,"")} ${if(type='年报'," and year(updatetime) = " + year,"")} 其中设置参数type的默认值日报,data的默认值是字符串2009-01-13 1.3 模板设计 模板样式如下 ![]() 2.4 绑定数据列 按照下表进行数据列绑定
2.5 参数设计 2.5.1 打开参数设计界面,参数界面布局如下 ![]() 2.5.2 控件设置 l type控件设置 右击type控件,选择控件设置,打开控件设置面板,控件类型为下拉框,控件名选择type,自定义数据,如下图所示 ![]() l date控件设置 右击date的控件,选择控件设置,打开控件设置面板,控件类型为日期,控件名选择date,自定义数据,如下图所示 ![]() l year控件设置 右击year的控件,选择控件设置,打开控件设置面板,控件类型为下拉框,控件名选择year,使用公式,dyear控件是由type的类型来决定他是否需要显示的,且我们默认的类型为日报,因此默认设置它为不可见,如下图所示 ![]() l month控件设置 右击month的控件,选择控件设置,打开控件设置面板,控件类型为下拉框,控件名选择month,自定义数据,并设为不可见,如下图所示 2. 事件编辑 右击type控件,选择控件设置,打开控件设置面板,添加编辑后事件,如下图所示:
在function fun(){}中添加如下代码: var form = this.options.form; var DateWidget = form.getWidgetByName("date"); var YearWidget = form.getWidgetByName("year"); var MonthWidget = form.getWidgetByName("month"); var value = this.getValue(); if(value == "日报"){ DateWidget.visible(); YearWidget.invisible(); MonthWidget.invisible(); }else if(value == "月报"){ DateWidget.invisible(); YearWidget.visible(); MonthWidget.visible(); }else if(value == "年报"){ DateWidget.invisible(); YearWidget.visible(); MonthWidget.invisible(); }else{ DateWidget.invisible(); YearWidget.invisible(); MonthWidget.invisible(); } 说明:此段代码的作用是选择日报,那么在其下方出现一个日期选择框;选择月报时,即让用户选择年月,例如2008年3月;年报与月报同理,即让用户选择年份。 3. 保存并预览 默认为日报,只显示出日期控件,预览效果如图 当选择月报时,右边弹出月份和年份下拉框,预览效果如图 当选择年报时,右边弹出年份下拉框,预览效果如图 ![]() 参数名的内部保留字段 对程序有所了解的都知道,各种程序开发语言中都有一些关键字,编程的时候定义变量名时是无法使用这些关键字的。FineReport出于特定的需求,FineReport在设计的时候也设定了一部分特定的关键词,在设计参数的时候,确保不要使用这些保留词,否则可能出现意想不到的错误。 FineReport中的内部保留字段有哪些呢?下面将把所有的关键词的名字以及意义列出来。 1. op op是FineReport中是用来确定不同的访问方式以及不同操作的参数 例:op=write,是填报的访问方式 2. reportlet reportlet是FineReport中确定访问模板的路径的参数 例:reportlet=/com/fr/demo/test.cpt 访问服务器中/com/fr/demo文件夹下的test.cpt报表 3. reportlets reportlets是在访问多张模板是使用的参数 4. sessionID sessionID是当前访问的报表的id参数 5. reportXML reportXML是用来传递修改过的报表模板的参数,使用在填报中 6. __cache__ __cache__是判断是否启用缓存的参数 7. __pi__ __pi__是判断是否显示参数界面的参数 8. __isdebug__ __isdebug__是判断是否启用debug模式的参数,使用jar包的时候该参数不起作用 9. $totalPage_number $totalPage_number是报表的总页数 10. $page_number $page_number是报表当前的访问的页码 11. _fr_authentication_key _fr_authentication_key是当前角色的认证信息,简单的讲就是这个参数在session中保存了角色-用户名-密码 12. fr_username fr_username是在使用权限时保存用户名的参数 13. fr_authority fr_authority是在使用权限时保存角色的参数 14. cluster_redirect 15. redirect_from 16. __isjmeter__ 17. __filename__ 18. form_value 19. format 20. __rtype__ 在定义参数的时候,注意不要使用上述FineReport的内部保留字段。 附:op参数常用的值如下(在浏览器中路径后面跟上&op=常用值,便能起作用) op=write 以填报方式查看报表 op=form以表单的方式查看报表 op=appserver查看当前服务器的基本情况(注册、内存、MAC地址等等) op=console_reg进入注册页面 op=fs 进入FineReport管理平台(暂定) 参数默认值 基本概述 参数默认值指:一个参数在被定义之后,预览时如果不给它赋值,则在筛选时采用它的固有值,这个固有值就是参数默认值。 参数默认值定义 报表中用来过滤数据的参数值可以设置默认值,这样当用户不输入参数值时将使用参数默认值进行数据筛选查询。 1.数据源参数默认值定义 在SQL编辑对话框中输入查询语句并定义参数如下 SELECT * FROM StScore WHERE ClassNo = '${ClassNo}' ${}是FineReport规定的参数的格式,括号中的ClassNo为参数名。 可以在下方参数面板中设置参数默认值。 选中参数,点击编辑,打开参数编辑器,可以定义该参数的默认值类型及值。参数默认值的类型包含字符串,整型,布尔型,日期型,公式等等。 2.报表参数默认值定义 在设计器中,打开报表|报表参数,新增加一个参数p1。 其中可以填写默认值,点击红圈处下拉框可以选择更多形式的默认值,如下图
![]() 全局参数的打开方式,是在设计器中,打开服务器|全局参数,该对话框与报表参数的界面类似。 3.公式型参数默认值 说明:我们用报表参数定义参数的方法来设计报表,介绍参数默认值当中“公式”类型的使用方法。 公式=TODAY()返回的是以日期形式表示的今日的确切时间,如“ =YEAR(TODAY())返回值为目前的年份。 ![]() 此时,参数p1的默认值就会随着时间变动,实现了参数默认值动态改变的效果。用户可以根据自己的具体需要设置参数默认值的公式形式。 参数为空选出全部 选择特定的参数后,会返回我们要查询的数据,然而假如没有输入参数值,我们却仍需要返回数据时该怎样处理呢?以下就用一个例子实现这种参数为空时返回所有数据的效果。介绍数据源参数与报表参数的实现方法。 1.数据源参数实现参数为空选出全部 1.1 定义数据源 新建名为ds1的数据库查询,SQL语句 SELECT * FROM StScore WHERE 1=1 ${if(len(classno) == 0,""," and ClassNo = '" + classno + "'")} ${if(len(studentno)==0,""," and StudentNo = " + studentno )} 说明: where 1=1表示条件永真,防止没有之后的参数条件时,where多出而导致出错; len(classno) == 0表示参数为空; ${if(len(classno) == 0,""," and CLASSNO = '" + classno + "'")}表示当参数classno为空时,就返回空字符串,否则返回查询条件and CLASSNO = ' classno' 。 1.2 模板设计 模板定义如下 ![]() 绑定数据列
1.3 参数设计界面
1 打开参数设计界面,按照下图
![]() 1.3.2 控件设置 定义参数classno控件类型为下拉框,其他定义如下图
![]() 定义参数studentno控件类型为下拉框,并以classno的值进行关联查询,定义如下 ![]() 说明:动态SQL语句SELECT * FROM STSCORE where ClassNo = '${classno}'表示直接从数据表STSCORE选取符合参数classno的数据 1.4 保存并预览 点击设计器上的分页预览,页面如下图,不输入参数值,直接点击查询按钮,返回全部数据: ![]() 2.报表参数实现参数为空选出全部 2.1 定义数据源 新建名为ds1的数据库查询,SQL语句:SELECT * FROM StScore 2.2 模板设计、绑定数据列,步骤与1.4中完全相同,此处不用赘述 2.3 定义报表参数 在菜单栏选择报表|报表参数,打开报表参数面板,添加classno和studentno两个参数,默认值选择字符串形式,并留空,即表示默认值为空值,如下图 ![]() 2.4 添加过滤 选中A2单元格,添加过滤条件 ![]() 说明:其中if(len($classno)==0,nofilter,$classno)表示若参数classno为空,则不过滤,否则返回参数值。 2.5 参数设计界面 同步骤1.3。 2.6 保存并预览 ![]() 参数下拉框的值通过公式编辑 在常用的年报、月报、日报当中,经常需要通过下拉框选择查询的年和月。年份通常是连续的从某年至今年,而月份是固定的12个月。像这种情况怎样来定义参数下拉框的值呢?您可能会使用自定义来达到目的,但这种方法需要手动输入所需要的值,比较繁琐。此时可以使用公式来定义下拉框的值。具体设置如下 1. 定义两个参数:year和month 2. 参数控件设置 设置参数year的控件类型为下拉框,使用公式编辑,输入公式: range(1997,year(today())) 设置参数month的控件类型为下拉框,使用公式编辑,输入公式:range(1,12) 3. 查看效果 保存模板,并分页预览
![]() ![]() 参数与字符串拼接 在数据集sql查询中,有时定义的参数并不是我们所需的最终值,我们需要进行改变才能使用,这时,可以在查询语句中进行参数与字符串拼接来达到目的。 打开之前所做的模板%FR_HOME%\WebReport\WEB-INF\reportlets\doc\Tutorial\Parameter\paratype4.cpt 1.参数设计页面 如下图,将控件类型选择为下拉框,属性选择自定义,实际值和显示值改为数字 ![]() 2.模板设计页面 右键点击报表数据集ds1,点击编辑,将sql查询语句改为 SELECT * FROM STSCORE WHERE ClassNo= ${"'"+'Class'+classno+"'"} ${"'"+'Class'+classno+"'"}这个语句完成了字符’号和字符串Class与参数classno的拼接,如参数classno值为1,则公式拼接后值为’Class
![]() 3.模板预览 点击分页预览,效果如下 ![]() 将此模板保存为 %FR_HOME%\WebReport\WEB-INF\reportlets\doc\Tutorial\Parameter\paratype7.cpt 超链接引用JavaScript 该例子实现用户在点击超级链接的时候,根据输入的页码,来决定链接到指定的页面。 有两种引用方式: 1. 将写好的方法保存为js文件,放置在工程下,在超级链接中直接调用 1.1 新建报表 1.2 模板设计 在B3单元格中写入公式:=range(1,40),并将其扩张属性改为“从左到右扩展”,并将其设为居中,如下图所示: ![]() 1.3 添加超链接 l 右击B3单元格,选择超级链接,进入超级链接界面,点击添加JavaScript,如下图所示 ![]() l 写一段Js代码,内容为: function demo() { var test = function() { var num = parseInt(arguments[0]); contentPane.gotoPage(num); }; var value = FR.Msg.prompt("输入", "页码", 2, test); } 说明: var num = parseInt(arguments[0]); //获得输入框中输入的页码 contentPane.gotoPage(num); //跳转到相应页码 var value = FR.Msg.prompt("输入", "页码", 2, test); //参数分别为对话框标题、对话框内容、输入框默认值、回调函数 将此段内容保存为test.js文件 ,放在WebReport目录下,在超级链接界面中插入该test.js,并在下面的function fun()函数中调用demo(); 效果如下图所示: ![]() 1.4 保存并预览 点击超级链接,出现如下图所示的输入提示对话框 ![]() 在输入对话框中输入需要跳转的页数,并点击确定按钮,就跳转到相应的页面。 2. 直接在超级链接界面上写js方法 2.1 新建报表 2.2 模板设计 在B3单元格中写入公式:=range(1,40),并将其扩张属性改为“从左到右扩展”,并将其设为居中,如下图所示:
![]() 2.3 添加超链接 l 右击B3单元格,选择超级链接,进入超级链接界面,点击添加JavaScript,如下图所示 ![]() l function fun(){}函数中写入如下JS语句: function test(){ var num = parseInt(arguments[0]); _g('${sessionID}').gotoPage(num); }; var value = FR.Msg.prompt("输入", "页码", 2,test); 说明: _g('${sessionID}').gotoPage(num); //跳转到相应页码 如下图所示 ![]() 2.4保存预览 点击超级链接,出现如下图所示的输入提示对话框 ![]() 在输入对话框中输入需要跳转的页数,并点击确定按钮,就会跳转到相应的页面。 动态超级链接 FineReport提供了超级链接功能,直接右击单元格超级链接就可实现,但单元格超级链接是静态的,我们还可以在条件属性中添加超级链接,这样就能根据不同的条件来判断超级链接的指向,从而实现动态超级链接。下面就通过一个简单例子介绍一下。 1. 表样设计 表样设计如图所示 ![]() 2. 参数设置 l 定义参数 在菜单栏中选择报表|报表参数,打开参数定义面板,添加一个参数p1,默认值选择字符串形式,如图 ![]() l 参数界面设置 打开参数设计界面,按照下图安排参数的位置 ![]() 参数控件类型为下拉框|自定义,如图所示 ![]() 3. 实现动态超级链接 右击B2单元格,点击条件属性,添加两个条件属性。 第一个条件属性,属性选择超级链接,选中使用链接,并添加公式:$p1==1,如图所示 ![]() 编辑超级链接,添加网页链接,链接到htt://www.baidu.com,这样参数如果选择百度,就链接到百度主页,如图所示 ![]() 第二个条件属性,属性选择超级链接,选中使用链接,并添加公式:$p1==2,如图所示 ![]() 编辑超级链接,添加网页链接,链接到htt://www.google.com.hk,这样选择谷歌,就链接到谷歌首页,如图所示 ![]() 4. 保存并预览 点击设计器分页预览,选择百度,点击页面的超级链接,该超级链接链接到百度主页,如图所示 ![]() 下拉框选择谷歌,点击页面的超级链接,该超级链接链接到谷歌主页
更为动态的SQL 对于查询条件不定的情况,如参数过滤的列也是动态变化的,有时想用A列进行过滤,有时想用B列进行过滤。此时在FineReport中,可以将整个查询条件作为参数传入sql中,查询出对应的数据,定义形式如:SELECT * FROM [TableName] ${Condition},即把整个where语句作为动态的参数。 1. 新建报表 2. 定义数据集 新建数据库查询ds1,输入SQL:SELECT * FROM STSCORE ${Condition}; ![]() 如下设计报表 ![]() 数据列设置如下表
4. 定义参数界面 点击参数设计,参数界面布局如下 ![]() 5. 保存模板并预览 保存模板,点击设计器分页预览,输入动态的查询条件如:Where ClassNo='Class1',便可查询出数据,效果如下图:
内置查询界面布局与背景 FineReport内置的参数查询界面支持各种控件,用户可以直接使用FineReport默认的控件布局,也可以像数据列一样将控件拖至参数界面任意位置,根据需要进行布局。FineReport可以控制参数查询界面的位置、显示样式,也可以对参数界面设置统一的背景,以下分别进行介绍。 1. 默认的参数界面 FineReport会根据参数定义的顺序,默认生成一个排列较好的参数界面,不需要自己手动设置或者拖拽。但需要注意的是,FineReport默认参数界面只支持3或3个以内的参数,当参数个数大于3时,使用默认的参数界面,您可以看到,界面上面只会显示出3个,剩余的参数仍需要手动添加。 参数设计界面中的按钮“刷新参数界面”的作用就是将自定义的参数布局恢复为FineReport中默认的参数布局。如下图
![]() 2. 自定义参数界面 若您不想使用默认的参数界面,也可以自定义参数界面,只需要将参数窗口中的参数拖至您想要的位置,然后定义其控件类型即可。 点击参数设计界面,弹出是否使用默认参数界面对话框,选择否
![]() 点击“显示参数窗体”即可自定义参数界面了。 3. 参数界面位置和显示样式 FineReport可以控制参数界面在浏览器页面中的显示位置(居左、居中、居右),同时也可以控制参数界面的显示样式(内嵌式和弹出式)。设置位置如下图
![]() 注:延迟报表展示设置已在不延迟报表章节中详细介绍,此不再赘述 4. 参数面板背景 为了与报表风格相同或达到其他效果,可以设置参数面板的背景,可以为颜色、图片或其他等。
![]() 日期参数的格式化处理 日期的表示形式有很多种,有时我们习惯填写的形式与数据库存储的形式可能不同,此时,就需要进行日期的格式化处理。比如,将“ 新建一个报表工作簿,打开文件|新建报表|新建工作簿。 1.设置报表参数 打开报表|报表参数,新增加一个参数p1,如下图 ![]() 2.模板设计 打开模板设计页面,将B2单元格内容设置为公式=format($p1,"yyyyMMdd"),如下图 ![]() 3.参数设计 打开参数设计页面,选择默认生成参数页面,点击B2单元格控件,选择空间类型为日期,控件名设为p1,如下图 ![]() 4.分页预览 ![]() 点击分页预览,可以在浏览器中看到日期字符串已经被转化为8位数字形式。这个函数,也可以用在数据集SQL查询语句中,形如${format( 日期参数校验 内置参数查询界面当中可进行一些数据校验,例如有两个参数:开始时间和结束时间,结束时间必须在开始时间之后,否则进行提示。 1. 在提交按钮的事件编辑中写JS代码 1.1 新建报表 1.2 模板设计 按照下图设计模板 ![]() 1.3 添加数据源 新建一个名为ds1的数据库查询,SQL语句:SELECT * FROM EMPLOYEE 1.4 绑定数据列 按照下表进行数据列绑定
双击B5单元格,在过滤页面当中,添加条件: BIRTHDATE 大于或等于 $begintime AND BIRTHDATE 小于 $endtime 1.5 定义参数 打开菜单栏中报表|报表参数,新定义两个名为begintime,endtime的参数,如图 ![]() 1.6 参数设计 l 打开参数设计界面,参数界面布局如下
l 日期控件设置 右击begintime的控件,选择控件设置,控件类型选择日期,控件名选择begintime,具体设置如下图所示 ![]() endtime的控件同上 1.7 数据校验 右击查询按钮,选择控件设置,打开控件设置面板,添加点击事件,如下图所示 ![]() 在function fun(){}函数中写入如下JS语句: var start = this.options.form.getWidgetByName("begintime").getValue(); var end = this.options.form.getWidgetByName("endtime").getValue(); if( start == ""){ alert("错误,开始时间不能为空"); return false; }; if(end == ""){ alert("错误,结束时间不能为空"); return false; }; if( start > end){ alert("错误,开始时间不能大于结束时间"); return false; } 1.8 保存并预览 begintime输入为空,如下图所示
endtime输入为空,如下图所示 输入的endtime在begintime之前,校验如下图所示: 2. 在参数控件的事件编辑中写JS代码 2.1 设计模板 具体操作同上。 2.2 数据校验 l 右击begintime的控件,选择控件设置,添加编辑后事件,如下图所示: ![]() 在function fun(){}函数中写入如下JS语句: var start = this.options.form.getWidgetByName("begintime").getValue(); if( start == ""){ alert("错误,开始时间不能为空"); return false; }; 说明:这段代码是为了验证begintime输入不能为空。 l 右击endtime的控件,选择控件设置,添加编辑后事件,如下图所示 ![]() 在function fun(){}函数中写入如下Js语句: var end = this.options.form.getWidgetByName("endtime").getValue(); if(end == ""){ alert("错误,结束时间不能为空"); return false; }; if( start > end){ alert("错误,开始时间不能大于结束时间"); return false; } 说明:这段代码是为了校验endtime输入不能为空以及结束时间大于开始时间。 2.3 保存并预览 效果与在提交按钮的事件编辑中写JS代码一样 输入不同参数查询数据不变 在实际应用中,常常会遇到这样的情况,在设计器预览时输入参数值数据正常变化,但是在浏览器进行分页预览时,更改参数值报表查询出的数据却不变。 对于这种情况,可能的原因是您参数界面中参数控件的名字与参数名不一致导致。您需要核对您的控件名,该错误常常发生在如某张模板已经做好,但由于需要修改了参数定义,但未对参数界面作相应的修改,此时问题便出现了。 如下以实际的例子演示。 1. 新建报表 2. 定义数据集 新建数据库查询ds1并定义数据源参数class,SQL语句为: SELECT * FROM STSCORE where ClassNo = '${class}' 3. 模板制作 如下制作报表 ![]() 4. 定义参数界面 使用默认的参数界面,如下图: ![]() 5. 修改参数定义 由于需要,将数据源参数名改为classno,如SELECT * FROM STSCORE where ClassNo = '${classno}' 但未对参数界面进行修正,参数控件名仍为class,如下图 ![]() 6. 保存并预览 保存模板,进行设计器预览,对classno赋值能正确获得结果。但点击设计器分页预览,在参数界面中设置参数值时,由于在参数界面中输入的值是赋给参数控件,而参数控件又根据控件名与参数一一对应起来,此时控件名为class,而参数已变为classno,因此参数不能正确获得值,查询结果便出错了。 数据源复选参数 数据源在从数据库获取所需值时,不仅可以在SQL语句中使用单一参数进行筛选,而且可以使用复选参数进行数据筛选。 1. SQL语句中复选参数的定义 SQL查询多个结果的格式为: SELECT * FROM [Table] WHERE [Para] in ('para1','para2','para3',...) 此语句意思为从数据库表Table中取出字段Para值分别为para1,para2,para3等等的数据记录。 根据最终格式定义SQL查询语句如下: SELECT * FROM STSCORE WHERE ClassNo in ('${classno}') 定义参数默认值Class1 ![]() 2. 模板设计 使用数据集定义报表如下 3. 定义参数设计界面 3.1 参数设计 打开参数设计面板,按照下图安排参数的位置 ![]() 3.2 控件设置 右击B2单元格,选择控件设置,打开控件设置面板,类型选择下拉复选框,返回值类型选择字符串,并以“’,’”分割。 ![]() 这样操做的目的是为了将SQL中的参数classno可选值转换为以逗号间隔的单引号字符串形式,型如'Class1','Class2','Class3',符合SQL中参数多值查询的定义格式。 4.预览并保存 分页预览效果如下 ![]() |
|