BI Publisher报表开发一般流程

BI Publisher被广泛用在oracle诸多产品的报表开发中,也是一种非常优秀的企业级报表开发解决方案,以下均简称BIP报表开发。开发一张报表的完整过程应该是:首先创建package将报表中用到的数据整理到一张临时表中,通过data template取得临时表的数据,经过简单的处理,制定其结构,并且按照这种结构生成xml数据,最后xml结合layout模版生成出有制定布局的报表。因而,BIP报表开发一般由临时表的创建、报表包的开发、数据模型的定义、报表参数的定义、布局开发等五个方面,下面主要就这五个方面对BIP报表开发的一般流程做一个大概性的总结:

(1)临时表的创建

临时表在BIP开发中有很大的作用,具体的有关临时表创建的内容,可以参见我博客中《oracle临时表用法小结》这一篇文章,这里不多说。

(2)报表包的开发

BIP报表包的开发,包的写法跟一般的PL/SQL包的写法基本一致,都是由包头和包体两部分构成,但是报表包中的方法比较固定,一般包括before_report、after_report、load_data、validate_parameters这么几个。其中,before_report执行数据查询前的操作,例如参数的验证、数据的有效性等,如果before_report返回true验证通过,就会执行load_data加载数据,把数据存放在临时表中提供给报表使用。当报表执行结束后,调用after_report删除数据,报表的运行基本结束。其实,报表触发器实质上就是显示返回true或false的PL/SQL函数。有关报表包的开发,暂时参与的还不多,待后面有了一定的经验,再来这里详细的总结下,待续。

(3)数据模型的定义

数据模型的定义

图1:数据模型的定义

比如说我现在需要创建这样一个报表,来实现查找数据库中所有者为给定用户的全部的表,这里默认为RMS用户。那么首先进入oracle的BIP系统,创建一个新的报表,在报表中新建一个新的数据模型,我这里就随便举个名字为“New Data Set1”,然后选择数据模型的类型,这里提供的类型有:SQL查询、HTTP(XML Feed)、Web服务、数据模块、Oracle BI Answers、Oracle BI Discoverer、文件、MDX查询这几种,我见的比较多的是类型是SQL查询和数据模板,我下面分别以这两种为例介绍:

数据模板形式:

<dataTemplate name="template">
    <parameters>
        <parameter name="owner_name" dataType="character" defaultType="RMS"/>
    </parameters>
    <dataQuery>
    <sqlStatement name="Q1">
        <![CDATA[
            SELECT table_name, owner, tablespace_name from all_tables WHERE owner = :owner_name
        ]]>
    </sqlStatement>
    </dataQuery>
    <dataStucture>
        <group name="G_TITLE" source="Q1">
            <element name="表名" value="table_name"/>
            <element name="所有者" value="owner"/>
            <element name="表空间" value="tablespace_name"/>
        </group>
    </dataStucture>
</dataTemplate>

SQL查询形式:

SELECT table_name "表名", owner "所有者", tablespace_name "表空间" from all_tables WHERE owner = :owner_name

(4)报表参数的定义

由于我在设置参数的时候选择的类型是“菜单”,需要用到值列表,所以,下面首先介绍值列表:

值列表

图2:值列表的设置

新建一个值列表,取名为New List of Value 1,BIP中值列表的类型有SQL查询和固定数据两种,SQL查询就是值列表的数据来源于查询表,固定数据表示值列表的数据来源于自己人工设定的几个数据项,我在这里采用SQL查询的方式,并输入如上图所示的SQL代码。

报表参数的设置

图3:报表参数的设置

报表参数名的设置一定要与数据模板中定义的parameter的name属性一致,包括大小写也要一致,并且选择数据类型,我这里选择“字符串”,默认值为RMS,参数类型有文本、菜单、日期、隐藏、搜索这几种,我这里选择“菜单”,并且在“菜单设置”中选择值列表为前面设置的“New List of Value 1”。其中,“更改时刷新其他参数”的意思是当该参数更改后,其他相关的参数也相应的刷新一下,该功能主要用于实现级联操作。还有一个需要注意的是,当设置可以多选的时候,其返回值是类似''abc','efg','hij''这种(都是单引号),这个时候需要对返回值做下replace处理,然后想办法处理成abc,efg,hij这种形式。当设置成“可以全选”,那么传入系统的值将会是空值NULL。

(5)布局开发

没有上传rtf模板测试报表结果

图4:没有上传rtf模板测试报表结果

上图4就是该报表的一个结果,只是没有给报表创建合适的模版,所以显示出来的是一个XML文件内容,下面也就是我们第五步要做的,就是给报表开发一个布局。首先,将上面的结果以XML文件格式导出。然后使用Oracle的word插件BI Publisher加载XML文件,加载的方法是进入BI Publisher的“数据”菜单中,然后单击“加载XML方案”。

报表的RTF模板

图5:报表的RTF模板

加载了XML方案以后,按要求插入表或者表单,并且对布局做一定的调整,由于我这里的例子简单,布局就暂且做成图5所示的那样,做好以后保存为.rtf格式,然后上传到BIP系统中。然后,在BIP系统中创建新的布局,然后布局模板选择刚刚上传的.rtf文件即可。最后,保存一下所有的设置,然后点击“视图”,运行下报表,查看报表结果如下图所示:

报表结果

图6:报表运行结果

基本上按照上面的操作,就能够制作一个简单的报表了,但是仍然有一些问题需要注意下,下面简单的补充一些:

(1)数据模版的格式

<dataTemplate name="dataTemplateName" description="dataTemplate Description" dataSourceRef="ORCL" defaultPackage="employee" version="1.0">
    <parameters>
        <parameter name="department" dataType="character" defaultValue="10" />
    </parameters>
    <dataQuery>
        <sqlStatement name="Q1">
            <![CDATA[
                SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = :department
            ]]>
        </sqlStatement>
    </dataQuery>
    <dataTrigger name="beforeReport" source="employee.beforeReportTrigger" />
    <dataStructure>
        <group name="G_EMPLOYEE" source="Q1">
            <element name="EMPLOYEE_NUMBER" value="EMPNO" />
            <element name="NAME" value="ENAME" />
            <element name="SALARY" value="SAL" />
        </group>
    </dataStructure>
    <dataTrigger name="afterReport" source="employee.afterReportTrigger" />
</dataTemplate>

其中,parameters是报表运行的参数,triggers是报表运行的触发器,dataQuery是数据运行的结果集,dataStucture是数据结构。对应dataTemplate标签,dataSourceRef属性是指定数据来源,defaultPackage属性是需要调用的oracle包。<parameters>标签对于多个子<parameter>对应报表的参数。<dataQuery>包括多个子<sqlStatement>执行数据库的查询。<dataTrigger>是数据触发器,调用相应oracle包的方法,报表的触发器实际上是显示返回true或false的PL/SQL函数,这些函数在运行格式化报表时被执行。<dataStructure>是对查询到的数据进行组织,<element>对应一个需要在报表页面显示的标签。注意,beforeReport触发器放在<dataStructure>之前的任何位置,beforeReport触发器会在dataQuery执行前被触发;afterReport触发器需要放在<dataStructure>之后,afterReport触发器会在产生XML数据、离开的时候触发。

(2)数据分组与汇总

报表有时候,需要分组,统计基本数据。例如根据上面的模板,我们需要多每个部门下员工进行分组,然后统计各个部门的员工工资。分组在数据模板里嵌套分组就可以实现。汇总可以通过数据模板内置的 sum()实现。也可以在pkg里统计好,直接读取数据就可以。模板代码如下:

<group name="G_DEPT" source="Q1">
    <element name="DEPT_NUMBER" value="DEPTNO" />
    <element name="DEPTSAL" value="G_EMP.SALARY" function="SUM()"/>
    <group name="G_EMP" source="Q2">
        <element name="EMPLOYEE_NUMBER" value="EMPNO" />
        <element name="NAME" value="ENAME"/>
        <element name="JOB" value="JOB" />
        <element name="SALARY" value="SAL"/>
    </group>
</group>

我还是觉得,有些功能能在代码里面实现就直接在代码里实现比较好,尽量在开发报表的时候只开发布局。

(3)当参数类型为文本(Text)

当参数类型为文本的时候,设置的时候如果勾选了“文本框包括逗号分隔的值”,那么当输入的文本中不包含逗号的时候,不论勾选或不勾选,其效果是一样的。但是,当输入的文本中带有逗号的时候,比如输入a,b,c,那么当复选框勾上时,传入系统中的值就是'a','b','c',没勾选的时候是a,b,c,就是说当勾选的时候,系统会以逗号为标志将字符串分为很多部分,并将每一部分用单引号括起来。

2015年04月08日补充:

在使用数据模型并且用到触发器准备数据的时候,定义报表包需要注意:

(1)触发器的入口必须是包的函数,即必须定义成函数function。

(2)在包的头定义中,加上BIP中传入的参数定义。

(3)函数function的返回值必须是boolean,尝试过设置成varchar,结果会一直报错。

本文标题:BI Publisher报表开发一般流程

本文链接:http://yedward.net/?id=61

本文版权归作者所有,欢迎转载,转载请以文字链接的形式注明文章出处。

相关文章