化递归树结构数据集为多层级树形结构数据集供报表使用

需求背景:

 

我们常常会看到数据库中的表是以id与其父id建立数据间的层级关系的,例如下图递归树数据结构:

通过上面的递归树数据,我们很难直观的得出表中数据共含有多少个层次。在进行报表制作的过程中,比如树形报表制作时,需要利用父id过滤选出的每层数据。在层数较多且层数不固定时报表制作将会相当麻烦。

本文利用递归算法,根据id与其父id一次性生成所有的层次,化递归树结构的数据为多层树形结构的数据供报表使用,可以大大简化报表制作的难度。

 

实现思路:

原数据集为递归数结构利用自定义数据集构建新的数据集,得到递归树的最大层级,根据最大层级构建数据集的列数,遍历原数据集的每一行数据,根据该行数据所在层数,填充其层数据和父层数据,最终得到多层级树形结构。其结构如下图所示:

 

具体实现:

1.自定义数据集类代码及说明:

publicclass MultiLevelDataSet implements IDataSetFactory{

    public DataSet createDataSet(Context ctx, DataSetConfig dsc, boolean retrieve){

       //读取同一报表中已算出的数据集,该数据集为递归数结构

        DataSet ds1 = ctx.getDataSet("ds1");

        //计算递归树最大层数

        int maxlevel=getMaxLevel(ds1);

        System.out.println("层数="+maxlevel);

        //根据最大层数构造数据集ds2

        DataSet ds2 = new DataSet("ds2");

        for(int j=1;j<=maxlevel;j++){

           ds2.addCol("level"+j);

        }

        for(int g=1;g<=ds1.getColCount();g++){

           ds2.addCol(ds1.getColName(g));

       }

        //根据ds1的数据填充ds2中每行数据

        for( int i = 0; i < ds1.getRowCount(); i++ ) {

           Row row = ds2.addRow();

           int level=getLevel(ds1.getData(i+1, 1).toString(),ds1);

           String curid=ds1.getData(i+1, 1).toString();

           while(level>0){

              row.setData(level, curid);

              curid=findParent(curid,ds1);

              level--;            

           }

           //拷贝ds1中原数据值ds2中对应列

           for(int k=1;k<=ds1.getColCount();k++){

              row.setData(k+maxlevel, ds1.getData(i+1, k));

           }         

       }

       System.out.println("ds2的总列数:"+ds2.getColCount());

       return ds2;

    }

    //获取数据集中递归树的总层数

    publicint getMaxLevel(DataSet ds){

       int maxlevel=1;

       //逐行遍历ds中的数据,计算每行数据所在层数,比较返回最大层数即为递归树最大层数

       for( int i = 0; i < ds.getRowCount(); i++ ) {

           int level=0;

           level=getLevel(ds.getData(i+1, 1).toString(),ds);

           if(level>maxlevel){

              maxlevel=level;

           }

       }

       return maxlevel;

    }

    //寻找当前节点(元素)的父元素

    public String findParent(String id,DataSet ds){

       for( int i = 0; i < ds.getRowCount(); i++ ) {    if(id==ds.getData(i+1,1).toString()||id.equals(ds.getData(i+1,1).toString())){

              return ds.getData(i+1,2).toString();

            }

       }

       returnnull;

    }

    //计算元素的所在层数

    publicint getLevel(String id,DataSet ds){

       int level=0;

       while(id!=null){

           id=findParent(id,ds);

           level++;

       }

       return level-1;

    }

}

 

2.自定义数据集的配置:

3.转换为多层树形结构后的应用实例

1)多层分组报表:

2)树形结构报表:

 

 

 

3)下拉树填报

posted @ 2012-04-19 16:13  报表技术  阅读(1152)  评论(0编辑  收藏  举报