api实现报表上分页下分栏的复杂需求

随着客户需求的日益复杂化,简单的报表或者相对复杂的报表设计已经不能满足一些特定的需求,这时需要利用一些方法来实现,例如通过api的方式来完成这种非常复杂的报表需求。

 

需求案例:

在报表中,可以方便的设计分栏报表进行展现,但是如果报表一部分要是正常的网格式报表,一部分又是分栏报表而且还要使用分组表头来进行多表头的处理该如何呢?通过设计器可以将此类报表设计出来,如下图所示,利用标题区、主子表以及润乾特定的分组表头分栏的功能。

 

可是这样的话会产生了一个新问题,如果子表中数据很多的话,由于行属性级别的限制,子表标题区域是不能分页的,那么有什么办法可以做到上半部分既能分页,下面的区域又能分组表头的分栏呢?

 

解决方案:

首先将这张主子表拆开,做成两张单独的报表,原来的子表下文称作报表A,原来分栏的部分下文称作报表B。如图所示。

 

接下来的工作就是将这两张表拼在一起了,我们可以这样想象下,当报表A输出在页面中进行分页,到最后一页,需要继续输出报表B的部分,可是由于报表B时分栏报表并且有多表头的输出,所以在分页时会严格控制输出的位置,所以不能单纯的直接拼上。

我们需要先计算出报表A最后一页的行数,然后在报表B输出前加上这个空的区域,这样才能做到两张表合在一起后的格式数据都正确的。

 

下面是相关的代码,通过传递参数模拟了分页的方式:

       int testpage = Integer.parseInt(request.getParameter(“page”) == null ? “1″ : request.getParameter(“page”));//通过参数模拟了分页

       PrintWriter out = response.getWriter();

       Context cxt = new Context(); // 构建报表引擎计算环境

       ReportDefine rd = null;

       ReportDefine rd_sub = null;

       try {

           // 首先计算报表A

           rd_sub = (ReportDefine) ReportUtils.read(“D://pp_sub.raq”);

           Engine engine_sub = new Engine(rd_sub, cxt); // 构造报表引擎

           IReport iReport_sub = engine_sub.calc(); // 运算报表

           // 对报表A进行按页拆分(除最后一页,因为最后一页后面要放在报表B的部分)

           PageBuilder pb_sub = null;

           pb_sub = new PageBuilder(iReport_sub);

           int pagecount_sub = pb_sub.getPageCount();

           // 页数小于报表A总页数,输出报表A(等于的话,展现报表B第一页)

           if (testpage < pagecount_sub) {

              IReport ir = pb_sub.getPage(testpage);//获取报表A不同页

              String htmlText = ReportUtils.toHTMLString(ir, “report1″,

                     request);

              out.println(htmlText);

           } else {

              testpage = testpage – pagecount_sub + 1;

              // 取得报表A最后一页,获取行数

              IReport ir_end = pb_sub.getPage(pagecount_sub);

              ir_end.getRowCount();

              // 将报表B中增加取得的行数并设置行属性为标题

              rd = (ReportDefine) ReportUtils.read(“D://pp.raq”);

              rd.insertRow(1, ir_end.getRowCount());

              for (int i = 1; i <= ir_end.getRowCount(); i++) {

                  IRowCell rowcell = rd.getRowCell(i); // 根据行号获得行首格

                  rowcell.setRowType(IRowCell.TYPE_TITLE_HEADER);

              }

              Engine engine = new Engine(rd, cxt); // 构造报表引擎

              IReport iReport = engine.calc(); // 运算报表

              // 计算报表B第一页,之前已经添加了空白行,将报表A的最后一页写入报表B的空白行中.

              PageBuilder pb = null;

              pb = new PageBuilder(iReport);

              int pagecount = pb.getPageCount();

              if (testpage == 1) {

                  IReport ir_begin = pb.getPage(1);

                  for (int i = 1; i <= ir_end.getRowCount(); i++) {

                     for (int j = 1; j <= ir_end.getColCount(); j++) {

                         INormalCell iCell = ir_end.getCell(i, (short) j);

                         ir_begin.setCell(i, (short) j, iCell);

                     }

                  }

                  String htmlText = ReportUtils.toHTMLString(ir_begin,

                         “report1″, request);

                  out.println(htmlText);

              } else {

                  // 计算报表B第二页后面的内容

                  IReport ir = pb.getPage(testpage);

                  String htmlText = ReportUtils.toHTMLString(ir, “report1″,

                         request);

                  out.println(htmlText);

              }

           }

       } catch (Exception e) {

 

           e.printStackTrace();

       } catch (Throwable e) {

           // TODO Auto-generated catch block

           e.printStackTrace();

       }

 

最终将两个报表计算后拼接到一起,页面效果: