如何在分组报表中实现组内数据补空行及组内页码
【摘要】
在分组报表中,按某字段分组后,组内数据较多时一组会分多页显示,并且一组数据显示完成后要求下组从新的一页开始显示,这样就要求某组数据展示完后,如果数据不满整页,需要补足空行以达到更好的效果,某组分页后要求组内页码的生成以及页内小计功能,点击如何在分组报表中实现组内数据补空行及组内页码查看具体做法。
在对报表数据进行打印时,经常会要求进行精确打印,比如一张纸能打印 20 行数据,如果超过就分页,如果不满 20 行,则在数据下方进行补够空行。这种情况最常见于银行对账信息等明细数据的打印。同时,在某些业务中还会按照一些字段分组,比如地区、类别等,在报表展示或打印时则要求先按照字段进行分组,将分组字段相同的数据放到一组内进行明细数据的打印,并在组内要求实现补空行操作。另外,对于分组数据,打印时所显示的页码要求是组内页码,比如报表总共 10 页,某一组分三页,则该组内页码应该显示为“第 1 页 / 共 3 页”。当然,最常见的每页打印表头也一定是需要的。
总结起来,其实是四点:
一:每页的表头;
二:报表分组后,每组的表头以及布局;
三:要求每组内数据补足空行,打印时每页都占满整张纸张;
四:组内页码。
下面是一个实际例子的效果图:
熟悉报表工具的同学都知道,报表中可以设置表头、分组表头,这样前两点就 OK 了。然后,我们可以算出数据条数用 to 函数进行补空行,第三点也满足了。但是,第四点,组内页码却无法实现,报表内置的 pno() 等函数都是相对于整张报表的,无法确定到组内是第几页,所以 pass,只能换种方式实现:“人为分页”。何为“人为分页”?就是在报表中根据特定的方法人为的去指定分几页,每页取什么数据。
下面通过一个报表介绍一下实现的过程。先看一下数据集的结构:
报表展示时要根据 MDS_OPERATION_SEQ_ID 字段进行分组,然后取出其他字段的明细数据,经测算,在 A4 纸上打印时刨除表头信息,能够打印 19 行数据,所以打印时要求每页打印 19 行,超过数据分页,不满 19(或 19 整数倍)则补空行。
看下整个报表设计模板:
首先报表要求表头信息每页都打印,此处可以使用报表的左主格,以要求报表纵向扩展时实现跟随扩展,将 A1~A7 合并,这样 A1 单元格就是后边单元格的左主格,A1 每纵向扩展都会实现后边区域的跟随扩展,A1 单元格表达式为:=ds2.group(MDS_OPERATION_SEQ_ID;MDS_OPERATION_SEQ_ID:1),该表达式按照 MDS_OPERATION_SEQ_ID 分组。
A1 单元格按照字段分组后,组内数据可能是多页,所以要在 B1 单元格中再进行一次分页操作,同样 B1~B7 单元格合并,里边表达式为:=to(1,if(ds2.count()%19==0,ds2.count()/19,int(ds2.count()/19)+1)),这里用到了 to 函数来实现扩展几页,具体页数要根据分组后数据条数来确定,之前说过每页能显示 19 行,所以表达式中是根据 19 进行了判断,如果表达式 ds2.count()%19==0 成立,表示数据量是 19 的整数倍,所以此时该组分 ds2.count()/19 页,否则分 int(ds2.count()/19)+1) 页,int 函数为取整操作,这样 B1 单元格实现组内页数的扩展。
页数取出后,接下来要进行数据行的操作,在 C6 单元格中写入表达式:=to((B1-1)*19+1,B1*19),该单元格同样用到 to 函数实现数据扩展,用来根据 B1 单元格(页数)里构造一个纵向的扩展区域,如果 B1 中分了两页,则 C6 会扩展出两片区域 119,2038,这样 C6 这就能构造出 19 的整数倍行(视页数定),也就实现了补空行的操作。
通过 A、B、C 三列现在实现了按字段分组、获取页数并且根据行扩展构造出了整个展示的轮廓,下面看下怎么将数据和之前模拟扩展的行关联上,在 D6 单元格中写入表达式:=ds2.select(#0)(C6),#0 是报表在数据集前默认保留了一个序号列,=ds2.select(#0)可以理解成是一个数组然后后边的 (C6) 是根据 C6 取数组中的第几个值,这样,就能将 ds2 数据集和扩展行关联上,在实际中有可能该组只有一条记录,也就是 =ds2.select(#0)是 1 条, (C6)是对数组操作,所以会报错,修改 D6 表达式为:=if(ds2.count()<=1,ds2.#0,ds2.select(#0)(C6)),先根据条数判断下,再决定返回什么表达式。
这样前四列结果如下:
在 D 列中取出了 ds2 数据集中的 #0,在 E6 单元格中写入表达式:=ds2.select(ID,#0==D6),根据#0 列做为条件取出对应的 ID 字段,后边其他列就是常规的网格式报表的制作,直接用数据集. 字段名即可。
上面实现了分组报表的表头每页可见、数据补空行操作,接下来看下怎么实现组内页码的操作,之前说过,在 B 列中根据数据条数能够获取该组内一共分了几页并进行 to 的纵向扩展,组内页码可以直接获取 B1 单元格的值就是组内的第几页,在 L3 单元格中写入:=“第”+B1+“页 / 共”+count(B1[A1]{})+“页”,此处获取总页数时,要获取该组内一共几页,表达式为 count(B1[A1]{}),此处用了润乾报表特有的“位移坐标”概念(位移坐标具体用法见《报表高级设计》),取该组(A1)内扩展出的 B1 的数量。这样,就实现了组内页码的需求。
最后,将 A~E 列隐藏,将 C7 单元格的行后分页属性选中以实现强制分页,最后再按照实际要求设置报表样式,这样就实现了报表分组时组内页码及补空行的操作。最终效果如下:
由本例可以看到,不管用户需求千变万化,除了使用在报表工具中自带的一些分页方式外,我们还可以自己在报表中根据用户需求做更加灵活的设置。通过行后分页属性,可以在指定位置进行分页,根据 select 的集合属性,可以取集合中的某个值,从而实现数据集和人为定义出的扩展数据之间的结合。
扩展:
此例中通过 B1 的 to 函数模拟出了组内分了几页,所以在表中同样可以实现分组后的页内小计和组内合计,直接用 sum(单元格 {}) 即可。
更多报表样式类问题请看:报表样式分类导航
* 按段分组报表制作
* 如何开发主从报表
* 报告式报表的制作
* 报表中如何实现不规则布局
* 报表工具轻松搞定卡片式报表
=if(ds2.count()<=1,ds2.#0,ds2.select(#0)(C6))
我的报表当数据只有一条时重复取值第一条,是哪里设置有问题吗?
直接改成 =valueat(ds2.select(#0),C6-1) 这个试下
谢谢已解决,再问一下,我的报表有一行作为合计,但是现在他会在分组和手动分页之后每页都计算合计,我想让它在打印最后一条数据之后再计算合计,可以实现吗?
现在的合计应该是每页合计,比如一组数据分了三页,那么每页都有个合计,你是想要个每组内一个合计就行了,还是整个报表就一个合计?
如果整个报表就一个合计,那么在报表最下方增加个合计行就行,这行不在前边的 group 合并格之内,这样就是整张表的最下方有个合计。
如果想每组内要一个合计,那么像你这个第 8 行这块,加合计,这时是每页合计,可以在这行的隐藏行表达式里边写个表达式动态控制,比如 B1 单元格是做了组内的扩展,可以根据这个格子是否是组内最大页码来决定这行是否隐藏,在隐藏行表达式里写 if(B1==max(B1[A1:0]{}),false,true),max(B1[A1:0]{} 这个表示取以 A1 为主格扩展出来的 B1 的最大值,也就是组内最大页码,判断下当前的 B1 是否是最大页码,如果是返回 false,表示不隐藏本行,否则隐藏本行