');
for 一级组织 in (一级组织的所有信息) loop
在此处查询该一级组织下的二级组织的个数 ln_row1
fnd_file.put_line(fnd_file.output
,'
');
for 二级组织 in(根据一级组织查询的所有二级组织的信息) loop
从报表可知该rowspan 值为1
fnd_file.put_line(fnd_file.output
,'
');
end loop;
end loop;
end loop;
该算法的优点:该算法能在输出之前根据需求算好该
’;
for orgnazation1 in () loop 二层循环
for orgnazation2 in () loop 三层循环
ln_month_row:= ln_month_row+1;--算月份行数
ln_row1:=ln_row1+1;--算一级组织行数
lv_orgnazation2_in:= '
';
lv_orgnazation2:= lv_orgnazation2|| lv_orgnazation2_in;
end loop;
ln_month_row:=
ln_month_row+1;--因为一级组织的合计,所以月份的行数要加上一级组织的个数
ln_row1:= ln_row1+1;--因为一级组织的合计
lv_orgnazation1_in:='
';
lv_orgnazation1:= lv_orgnazation1||
lv_orgnazation1_in;
ln_row1:=0;
end loop;
--在此处开始输出报表的内容
fnd_file.put_line(fnd_file.output,lv_month);
fnd_file.put_line(fnd_file.output, lv_orgnazation1);
fnd_file.put_line(fnd_file.output, lv_orgnazation2);
--输出完之后所有变量清0,以保证下个循环的输出正确
ln_month_row:= 0;
lv_orgnazation1:=null;
lv_orgnazation2:=null;
end loop;
使用字符串缓冲区的优点:使用字符串缓冲区相比上一种方法来说可以实现在文档中不存在SQL,而且可以不在乎不同一级组织下的重名问题。
使用字符串缓冲区的缺点:使用的变量比较多,而且在算行数的时候的逻辑容易乱,每个循环后应该清0和清空的变量要明白清楚,整个代码的逻辑自己要清楚;字符串缓冲区的大小有上限,如果数据过大超过上限就会报错,clob变量可以解决这种问题,但其用法比较复杂,不建议使用。
1.3行列均动态
上述两种情况的合并使用。
2 整体数据筛选逻辑的设计
目标:保证数据正确、满足需求且唯一。
2.1 确定满足需求的字段的判定条件
2.2 多表连接筛选数据
2.3 自然语言描述报表逻辑画程序流程图
三 代码实现(按HTML的报表输出格式分类)
1 不使用Html报表模版输出
1定义相关变量;
2定义css样式;
3定义游标CURSOR,将报表的主查询语句,作为其查询部分;
4用html输出报表标题;
5输出参数及其值;
6输出表格内的标题;
--输出方法参见表头设计
7按报表参数的条件组合做出条件判断;
8通过FOR REC IN CURSOR LOOP方式的循环,查询内容,逐行输出;
9在循环过程中,可以通过SELECT INTO的方式将游标查询中未能反应的数据,存入变量中,在输出时灵活运用;
10在小计或合计的地方注意在隔层循环外变量的清零;
11设置报表权限;
12提交报表;
2 使用Html报表模版输出
此处以刘宏老师给的模版为例说明:
1确定xxhan_htm_util_pkg.pck和xxhan_cux_util_pkg.pck这两个包在数据库内,并且可执行;
2根据报表输出样式定义一个PROCEDURE regist_templates,regist_templates
中要灵活使用,regist_templates模版中的各个块的含义一定要清楚;
3 之间设置满足需求要求的css样式,美化报表、满足用户体验。
四 报表数据测试
1 测试准备工作:
数据准备
保证足够多的有效数据
清楚报表中涉及到的算法、公式
清楚业务功能接口
2 报表测试点
1)基本测试点:界面、格式、布局、明显的数据错误、报表标题,报表整体风格;
2)有效数据准确性验证:数据的来源、数据的对应关系、数据的格式、数据的排序、明细与合计的一致性;
3)报表查询:覆盖所有的查询条件,输出结果准确;
4)汇总,明细表数据间的关联以及多张报表之间的比较;
5)日期字段:关系到结算,查询,统计等;
6)权限控制和安全性测试:报表查看权限;
7)报表的辅助功能:Excel导出、打印等;
8)样式统一:查询条件的保存、单位的统一等;
9)测试前的评审工作(即互测):测前组织测试评审或者测试交流,对测试的深入,对接口,取值,数据的来龙去脉等重点或主要功能的讲解要详细,(除简单测试点外,其他要尽可能详细)。在交流前自己要先大概了解报表的功能,这样效果会更好;
10)代码走读或者查询日志:熟悉程序逻辑结构,熟悉报表结构的情况下可以发现业务功能的逻辑bug,fnd_file.put_line(fnd_file.log,'message');
--信息写在log中可以查看日志文件的报表执行顺序和发现问题或者设计不合理的地方;
11)
测试数据:自己首先添加简单的数据,验证报表统计数据的正确性。然后,再添加数据模拟业务的所有流程产生的数据,验证所有业务流程下数据的正确。这样一步步地深入,可以使得测试思路清晰,容易定位报表设计的业务。(正式数据最好);
12) 测试中借助数据库做数据的验证测试。
一级组织
二级组织
..
嵌套表的优点:嵌套table的方法在使用时不用去考虑一级组织和二级组织的行数,只需要按照HTML的格式在输出部分循环输出就可以。
嵌套表的缺点:嵌套table的方法的缺点很明显,数据可以按照你想实现的实现,但是表的各种属性要严格控制,否则就出现上下列不对齐,而且嵌套table的方法在循环输出的时候要严格控制它的开始输出的HTML标记和在循环结束时应该有的结束标记,表格嵌套的越多逻辑越容易乱
注意:在使用嵌套table的方法时要注意表头是作为一个table标签的,否则就会出现列不对应的情况,如下图。表头也使用嵌套,通过ID来标识它们的一一对应性。
2) 在输出之前算好该
标签的rowspan值
例如在此报表中,月份的rospan值就应该是所有的二级组织的行数再加上所有的一级组织的行数(因为每个一级组织有个合计要算),;然后一级组织的rospan值就是该一级组织下的所有二级组织的行数再加上1(因为该一级组织有个合计要算)。每个rowspan都应该在输出之前将其算好赋予一个变量值,然后在输出的时候将此变量值传到HTML的rowspan中。例如此报表的处理方式如下:
先算出所有的二级组织的行数和一级组织的行数之和ln_month_row,此为月份的rowspan值
for v_month in 月份的游标 loop
fnd_file.put_line(fnd_file.output
,'
' ||月份|| '
' ||一级组织|| '
' ||二级组织|| '
报表二级组织后面的列
的rospan值,能实现报表的表样,相比于嵌套table的方法该方法在表样格式上控制简单,而且报表格式良好。
该算法的缺点:在算行数的时候如果二级组织有重名(即不同一级组织下有相同名字的二级组织)就会影响到行数的算法,对此的处理使用的是在查询时加上之前的一级组织字段,保证唯一,即:
select distinct 一级组织字段,二级组织字段
from 表;
如果二级组织为空没有值,也会影响到行数,在输出时需要判断rowspan是否为0,如果为0则让其为1,二级组织为空,这样报表才能出来。
3) 使用字符串缓冲区
使用字符串缓冲区的方法是将一级组织和二级组织的信息先显示出来但不输出,在每层循环里面用一个变量来统计rospan,并将该循环的内容放到一个字符串缓冲区内,直到所有的循环跑完之后,再输出这个缓冲区的内容。具体介绍以此报表为例
先定义字符串缓冲区和变量
lv_month varchar2(32767);(32767为varchar2的最大值)
lv_month_in varchar2(32767);
lv_orgnazation1 varchar2(32767);
lv_orgnazation1_in varchar2(32767);
lv_orgnazation2 varchar2(32767);
lv_orgnazation2_in varchar2(32767);
ln_month_row number;--月份行数变量
ln_row1 number;--一级组织行数变量
for v_month in (月份游标) loop
一层循环
lv_month:=’
月份
' ||二级组织|| '
此处开始输入二级组织后面的列
' ||一级组织|| '