zoukankan      html  css  js  c++  java
  • 2019-1-17水晶报表技巧总结【二】

    2019-1-16水晶报表技巧总结【一】

    2019-1-18水晶报表技巧总结【三】

    第一条:水晶报表分组分页且每页最多显示N条记录

    第二条:一个获取记录的标记和页脚的显示

    第三条:页面大小的设置。

    第四条:如果要让列分上下两处显示---要用到子报表。把子报表和主报表做成一样的格式。

    第五条:推拉说识 

    第六条:一种根据记录数和前面一行的内容和后面一行的内容不一样而分页 

    第七条:主报表和子报表共享数据 

    第一条:水晶报表分组分页且每页最多显示N条记录

    返回顶部

    要求:1、详细节最多5条记录(不能超过5条);
               2、无论前一组是否满5条记录,每个新组都要另起一页

               3、可以显示组内分页的情况,即:显示一个组被分为几页并且当前是第几页

    我们知道每页最多显示N条的控制方法,打开节专家,在详细节后面新建页公式编辑:
    RecordNumber mod N = 0

    RecordNumber即记录数,无论分组与否,是自动随记录递增的,所以在这里,我们不能用RecordNumber,而应该是在每个新组前要重置这个RecordNumber,用这个重置的RecordNumber来取模控制每页最多显示5条记录,于是我们很自然就想到了运行总计字段,由它来帮我们重置RecordNumber,

    这样我们应该就很明朗了,接下来让我们一起去设计模板:

    报表按ID分组就不用再提及了吧?(右击报表空白处->插入->组)
    首先新建一>运行总计字段
    汇总字段:XXX(最好选择的字段和分组字段不同)

    汇总类型:计数
    求值:对于每个记录
    重置:组更改时
    设计好后把,字段放到【详细资料】中,根据需要可以抑制显示。
    点击节专家,【详细资料】-->【在后面也新建页】勾上-->设置公式
    字段是刚刚建立的【运行总计字段】
    {#RTotal0} mod 10=0 
    

    针对需求2,与需求1同理,只不过此时我们是在#组尾(组页脚)节在后面页新建页的公式编辑:

    Not OnLastRecord

    OnLastRecord意指最后一条记录,Not OnLastRecord自然是非最后一条记录,在这里就是指非最后一条记录时就在后面页新建页,最后一条记录时就不用再新建页了。若不用该公式控制的话,报表的最后一页总是空白页(没有详细节数据)
    需求3:组内分页及显示页码

    新建一个【公式字段】公式设置如下:

    记录的组记录总数:count(一个报表参数,分组参数);前者最好是运行总计的字段。如果有汇总,请在count最后+1,因为多一行数据。!!!

    组内条数和当前组内序号,这两个最可能出现有误,在序号为9或者11,就是比你设定的行数大 “1”。

    方式一:注意组内数据条数当前组内序号

    //每个组的总记录数
    NumberVar groupRecordCount := Count ({DataTable3.Type}, {DataTable3.ID});
     
    //每个组的总页数 
    NumberVar groupPageCount := groupRecordCount / 5;
    If Int(groupPageCount) <> groupPageCount Then
    (
      groupPageCount := Int(groupPageCount) + 1
    );
     
    //重置后的RecordNumber
    NumberVar groupRecordNumber := {#RTotal0};
     
    //组内当前页
    NumberVar groupPageNumber := groupRecordNumber / 5;
    If Int(groupPageNumber) <> groupPageNumber Then
    (
      groupPageNumber := Int(groupPageNumber) + 1
    );
     
    //最终报表界面显示
    '第' + ToText(groupPageNumber, 0) + '页 / 共' + ToText(groupPageCount, 0) + '页'
    //说明:Int函数是取整函数,如Int(1.2)=1; Int(1.9)=1
    //写好后将该公式字段拖放到#组头(组页眉)节即可
    

    方式二:注意组内数据条数当前组内序号  如果有方法“RoundUp”的,可以把if直接换成此方法:p1:=RoundUp(x1/10); p2同理。

    numbervar x1;
    numbervar x2;
    numbervar p1;
    numbervar p2;
    
    //x1是每个组的数据条数
    x1:=count({OUT_1_DATASET.code1},{OUT_1_DATASET.Warehouse_position});
    
    //得到总页码
    if(x1%10=0)then
    p1:=x1/10
    else
    p1:=INT(x1/10)+1;
    
    
    
    
    //得到当前行组内序号。其实就是换页第一条的序号
    x2:={#RTotal0};
    
    //用序号除以每页的条数5,得到当前页码
    if(x2%10=0)then
    p2:=x2/10
    else
    p2:=INT(x2/10)+1;
    
    
    //组合
    '第'+totext(p2,0)+'页/共'+totext(p1,0)+'页'
    

      


    第二条:一个获取记录的标记页脚的显示

    返回顶部

    在IDE左侧的“字段资源管理器”里的“公式字段”点击右键“新建”,新
    
    建一个字段“Group”,编辑赋值:
    whilereadingrecords;
    true;
    这里是TRUE,获取的就是“真”,否则获取的就是“假”
    

      

    控制子报表每页显示数目,假设为10行每页,只是做一下说明,不要设置公式 
    注意设置的行数最好基本上能打印到页面的底部
    
    拆分一个详细资料节出来,把页脚内容写上,抑制显示,设置公式为 
    recordnumber mod 10<>0 
    在这个节上进行分页控制,“在后面页先建页面”勾上,设置公式为 
    recordnumber mod 10=0
    
    这样的话每页最下面会显示该节模拟页脚 
    最后一页如果不满10行的话,因为你设置了报表页脚,也可以模拟成一个页脚了 
    为了防止最后有一页刚好显示10行导致出现双重页脚 
    还需要进一步改进一下抑制显示的公式 
    If onlastrecord then 
    true 
    else 
    if recordnumber mod 10<>0 then 
    true 
    else 
    false
    
     
    
    最后页不足,用空行填充: (Basic语法)
    新增一个空白详细资料行,格式化此节,在抑制显示(无深化)打勾 
    公式中输入: 
    if not onlastrecord  then 
        FORMULA = TRUE 
    else 
       if (RecordNumber mod 5 <= 1) then  '第一个 
           FORMULA = TRUE   
       else 
           FORMULA = FALSE  
       end if 
    end if 
    

    第三条:页面大小的设置。

    返回顶部

    要现在本地的打印机上设置相应的纸张大小,然后应用到报表中。

    本地打印机添加新的打印纸张规格:

    WIN7系统中:设备和打印机-->菜单栏中【打印服务器属性】-->【表单】或者【格式】-->创建新表单-->输入相应的尺寸,点击保存即可。

    在报表中,右击报表的空白处:设计-->页面设计,填写相应的尺寸。设计-->打印设置-->在纸张中选择自己新建的纸张大小就可以了。

    第四条:如果要让列分上下两处显示---要用到子报表。把子报表和主报表做成一样的格式。如下显示:

    返回顶部

    合同编号:XM-003   供应商:广西中金公司
    合同条款                金额       
    付20%                   2000
    付80%                   8000
    付款日期      付款金额
    2011-10-1        10000
    2012-10-12       12000

    折开显示,每个页面就可以固定显示,这样按分组分页,防止数据过多分页时,子报表被分开。

     特别说明!

    使用子报表的方法,在数据量较大的时候,效率非常低。所以要慎重选择使用。

    如何将同一个表(记录集)中的字段,拆成上下两部分,每页各显示10条。
    也就是这个样子。
    有人可能一下子想到的就是两个子报表。
    如果数据比较少,不用分页,用子报表是没问题的
    但是如果要分页,子报表是做不到的(至少目前的水晶报表还不支持这个机制)。
    因为显然两个子报表都要分页(或者有人是用一个主报表,一个子报表)
    但是这样一个页面上就出现了两个分页需求,然目前水晶报表的解析,是用后面的规则去覆盖掉前面的规则
    也就是说,虽然确实都分页了,但是因为常规分页都是在详细资料节处新起一页的。
    那么第2个子报表和第1个子报表的内容会重叠起来。
    而如果把子报表放在不同的节上,又会出现这样的情况。
    就是第一个子报表全部分页结束,才会显示第2个子报表的内容。
    这样就造成了数据不连贯(当然,也有的需求直接就这样,那就直接这么用就可以了)。
    
    下面我开始示例操作
    
    1:样例数据
    本文以独立版本水晶报表自带的样例数据库xtreme.mdb中的Orders订单表为例。
    
    
    2:数据的整理
    数据必须有一个连续的ID(或者有一个分组的标志位),这是本文实现的重点。
    所以特别说明一下。
    我们的方案中,将以这个ID(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22...)为准进行处理。
    如每10个分一页,那么我们要构造一个分组字段:(ID-1)  10 
    注意这个符号,是取整的。
    这样,就把每10个归为一个组了。这个字段会出来一个0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3...
    当然,如果有条件,可以之前就准备好,比如说这个ID直接就是1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3...
    这里我先不讲为什么要这样做,只是你务必要注意这一点。
    不要依赖于数据库本身里的ID,因为你可以有不同的过滤条件及排序条件,会导致你的本身的数据ID是不联系的
    所以这个ID字段,是你自己构造的,与是原先数据并无实际的逻辑关系,只是为报表准备的。
    
    比如,以Access语法为例子,为现有记录集主动加一个ID列。
    SQL code
    ?
    1
    2
    3
    4
    SELECT (
    SELECT count(*) +1
    FROM [Orders ] as a  where a.[order id]<b.[order id]) AS  myIndex, b.*
    FROM Orders AS b;
    
    
    其显示的结果如下
    
    
    当然,我们也可以直接进去到前面说的第2种情况
    SQL code
    ?
    1
    2
    3
    4
    SELECT (
    SELECT count(*)]10
    FROM [Orders ] as a  where a.[order id]<b.[order id]) AS  myIndex, b.*
    FROM Orders AS b
    
    
    其显示的结果如下
    
    
    本文采用第一种方法来实现。
    
    3:数据与模板怎么进行连接
    我们已经知道制作模板有PULL和PUSH两种方法。
    使用PUSH的话,就不用关心这个操作了。因为这个SQL是在代码中实现并传给记录集的再传给报表。
    而使用PULL的时候,就这样,直接把SQL代码拷贝到“命令”就行了。
    当然,你也可以使用存储过程,或者一个中间的实体结果表等。
    
    
    4:制作主模板
    我们先用主报表来显示前半部分字段,然后用子报表挂接后半部分字段。
    两个报表可以使用同一个记录集
    不过如果数据量比较大,建议还是按照实际需要拆开,这样减小数据的传输
    如主报表的记录集只放前5个字段,子报表的记录集放后5个字段等。
    
    我这里为了方便操作,用了同一个记录集。
    
    
    <1>首先构造主表,做一个基础的明细表
    
    
    
    
    
    
    <2>构造分组字段myGroup1,进行分组
    如果是【2:数据的整理】中的第2种实现方法,则可以直接用ID作为分组字段了
    
    myGroup1公式如下:
    
    并进行分组,如果需要,把页眉放到组页眉上。
    
    
    最后出来的模板是这样的
    
    
    出来的数据是这样的
    
    
    好了,主报表操作完毕。
    
    5:制作子报表模板
    
    在模板上点右键,插入子报表。
    把这个子报表,拖到主报表的组页脚上。
    子报表的做法跟【4:制作主模板。】一模一样。
    (包括分组公式及操作)
    唯一的不同就是在模板上显示的字段不同,此处省略了。
    为了便于识别,把子报表上的字体全部设置为红色。
    把不需要显示的节,全部抑制显示掉
    
    
    
    6:设置主报表和子报表的关系
    
    这个时候报表大致就是这个样子的,在子报表上点右键,选“更改子报表连接”
    
    
    在出来的界面上,把两个分组字段关联起来。
    (我这里两个分组字段取的名称不一样,这个不影响操作)
    
    好了,再预览一下数据。这样数据就组合在一起了
    
    
    7:分页设置
    
    进入主报表的“节专家”,设置组页脚,勾选“在后面页新建页”就可以实现了。
    如下图我们切换到第3页。
    

     第五条:推拉说识 

    返回顶部

    .【水晶报表内功心法】--序言 
    .【水晶报表内功心法】--推拉之间
    .【水晶报表内功心法】--PULL模式样板招式

    特别说明:
    因为水晶报表里不认datatime型,对于2009-06-26 9:23:15
    会自动截断为2009-06-26
    所以datatime型数据在xsd文件中,可设置为string型
    而代码中的SQL中可把字段转换为String传入。

    这里做一下说明,在【推拉之间】没有说这个xsd,是因为当时没讲到细节操作。
    说了很难理解。
    这个xsd,是我们自己构造的,做个比喻吧:
    就是xsd比作个一个架子,它负责把水晶报表撑起来,但是是空的,没有内容
    我们用 PUSH模式,把数据塞给它,把架子塞满,这样水晶报表也就能呈现出效果来


    常见问题:
    1:报表可以显示出来,但是没数据,
    一般有以下几种情况
    a:表中确实没数据
    b:da.Fill(dt1, "mytable");表名称与xsd中设计的表不一致
    c: 如果你用了多个表,可能是因为表默认的关联关系导致无数据

    2:出现下面这个图的提示,特别是翻页、打印、导出的时候,因为这些动作都需要重新连接数据库源。
    a:如果是多表的话,可能是部分表没有赋值。
        水晶报表需要对用到的每个表进行验证,即使没数据。没有的话,传个空的记录集也行。
    b:代码没有放到Page_Load或Page_init里,或者是放到了,但是控制了 postback。
       因为http是无状态的,如果控制了postback,水晶报表就丢失了前面的设置,会导致出现此情况的

    第六条:一种根据记录数前面一行的内容和后面一行的内容不一样而分页

    返回顶部

    在报表上右键-->报表-->节专家-->详细资料-->在以下内容前新建页-- >右边的小方块中新建basic公式:
    
    水晶报表常规页码是以下代码的"3",满3行记录的自动换行,碰到TBUserInfo.SerialNo与上一行记录不同也换行。
    
    Shared SerialNoGG as Number
    Shared RecordTemp as Number
    if RecordNumber = 1 then
        SerialNoGG = {TBUserInfo.SerialNo}
        RecordTemp = 1
    end if
    
    
       if RecordTemp mod 3 = 0 or {TBUserInfo.SerialNo}<>SerialNoGG then 
          RecordTemp = 1
          SerialNoGG = {TBUserInfo.SerialNo}
          formula =true 
       else 
          RecordTemp = RecordTemp + 1
          formula =false 
       end if
    

    第七条:主报表和子报表共享数据

    返回顶部

    使用水晶报表变量实现主报表及子报表之间的数据共享

    在使用水晶报表子报表的时候,
    可能根据需要在主报表之间和子报表之间共享部分数据
    如子报表需要依据主报表的某些数据进行运算等

    因为主报表与子报表之间的数据是独立的,所以不能直接引用对方的字段等资源
    所以要得到对方的数据有些难度,
    有些朋友使用在代码中传递参数等方式来实现,
    其实在水晶报表中已经有了问题的解决方法,那就是公式中的共享变量

    大家可能注意到了在水晶报表的公式中定义的变量是有作用域的
    分别是Dim/本地(Local)/全局(Global)/共享(Shared)

    使用水晶报表的共享变量即可实现在主/子报表之间的数据共享

    在下面的例子中,我们以在子报表中获取主报表中的一个数据为目标来进行演示
    我们使用水晶报表的自带的数据库来做演示,在主报表中获取一定的数据
    然后进行汇总
    在子报表中获取这个汇总数据,

    以下的公式,使用Basic语法

    主报表中的公式如下
    公式名称:@fMain1
    公式内容:
    Shared myTest1 as string 
    myTest1={产品.颜色} '此处可以替换为任意想获取的数据
    formula = myTest1
    
    将该公式应用到主报表的适当位置,如果不需要显示,可以抑制显示
    不影响后续数据的获取
    
    子报表中的公式为:
    公式名称:@fSub1
    公式内容为:
    Shared myTest1 as string
    formula=myTest1
    
    将公式应用到子报表的适当位置,即可显示出主报表的内容
    
    注意:公式中的变量名称与类型需要一致!
    

      

    返回顶部

  • 相关阅读:
    安装wampserver时提示丢失MSVCR110.dll(在windows server上可用)
    前端开发必备!Emmet使用手册
    Markdown 新手指南
    封装系统(以封装Windows 7为例)
    简体中国版文档的Markdown语法
    sublime text 3 快捷键大全以及配置编译环境
    windows下的命令行工具babun
    Android屏幕适配全攻略(最权威的官方适配指导)
    JMETER第五节课jenkis集成常态化压测的实战?主从压力机实战??
    性能测试5--Jmeter命令行与以及普罗米修斯的原理
  • 原文地址:https://www.cnblogs.com/liuqifeng/p/10281408.html
Copyright © 2011-2022 走看看