(3)birt笔记

来源:互联网 发布:网易云课堂for mac版 编辑:程序博客网 时间:2024/06/11 04:23

在实际使用birt图表时,其提供的视图界面能够很高效的帮助我们创建出所需的报表,但是有时涉及到一些复杂的,x/y/显示数据都为动态的情况时,单纯使用界面编辑已经无法满足需要。例如现在需要一张折线图报表,x轴为课程(不确定有几门),y轴为分数,现在需要用折线图展示学生各门课程的分数(一个学生一条折线,学生数不确定),如果使用界面编辑,实际效果如下:
在图中左边的series x为代表学生的折线,假设有4个学生,我就需要在这里点击new series…4次来创建4条折线,但是就像上面所说的,学生数量不确定,所以在用试图界面编辑时,将会无法满足该需求,但是,不用担心,birt提供了java script脚本或者java脚本形式动态创建报表的功能。这里具体讲解下java script脚本方式吧
这里写图片描述
一些基本的创建,框架整合可以看我的上2篇文章,我这里用的框架就是上一章中整合完的

1.创建数据集

利用存储过程将查的数据组装成如下表形式:
这里每个学生的列名可以改为1,2,3这样,方便之后绑定,当然直接用学生名也可以,就是出现中文会麻烦点,PS:这里有一点比较麻烦的是如果列数不固定的话,数据集在初始化时将不会实时跟新,比如你第一次查出了10个学生,第二次查出20个,那么这里还是默认只有10个学生,所以建议加几个空白列,预先测定出学生数最大的情况,然后在生成表时不足的部分用空白列填补(列名数字的话继续增大),所以最后我使用了数字作为列名。
这里写图片描述

在birt数据集中调用存储过程和直接查表的用法类似,具体如下:

//有2中方法,如果需要动态查询/对所传参数需要进行拼装则建议第2中方式//1.视图界面{ call dbo.存储过程名(x)}//data set双击点开的视图界面中写法,x为传入的参数//2.java script脚本(单击data set中所想要编辑的数据集,然后点击图表编辑界面下方的script按钮,选择beforeOpen)//此时视图界面就不需要填写sql语句了var query="";query+="call dbo.存储过程名称('"+params["x"]+"',)}";this.queryText=query;

1.视图界面填写sql地点
这里写图片描述
2.java script脚本添加地点,这里也可以看出我在调用存储过程前还对传过来的参数进行了一些拼装,语法完全遵循java script
这里写图片描述

数据集创建完成后可以预览下数据集是否正确(即是否会返回表数据)
双击数据集,点击如下红框中的按钮,如果右边的预览结果出现表了,则正确,如果sql语句有问题,这里就会报错,报错时可以点击detail,其中中间位置有一条最长的报错信息,看具体内容来修改sql(这里挺麻烦的,因为报错不会告诉你sql哪行出错了,具体还是要自己看,最坑爹的就是单引号这类转义字符,要非常小心)
这里写图片描述

至此,数据集创建完毕

2.创建折线图

建立一个折线图,数据就x轴填写1中样式中的课程那一列,y轴就填id那一列(该id折线实际上没什么用,不过y轴不添加一条折线的话会报错,所以才加了条id,id列值都是0都没问题,之后会将该折线隐藏)
这里写图片描述

把id折线隐藏掉,红框不打勾即可
这里写图片描述

然后点击完成
我们就得到一张空白的折线图了,在红框中输入该折线图的名字,之后添加折线时会用到
这里写图片描述

编写java script脚本动态添加折线

1.java script脚本

在图表预览界面,在图表外的灰色部分左键单击,然后选择下方的script,选择beforeFactory,编写代码,因为如例子中所说,需要绘制各个学生的折线图,这里就需要先获得学生数(名字数组),可以通过引入java函数的方式返回查询出的学生数(名字数组),即实现了一个图表使用了多个数据集

importPackage(Packages.org.eclipse.birt.chart.model.data.impl); importPackage(Packages.org.eclipse.birt.chart.model.component.impl); importPackage(Packages.org.eclipse.birt.chart.model.type.impl); importPackage(Packages.org.eclipse.birt.chart.model.attribute); importPackage(Packages.org.eclipse.birt.chart.model.attribute.impl); //调用的java方法所在的包 importPackage(Packages.com.springMVC.controller); chart1 = reportContext.getDesignHandle().findElement("deptTitle");   //获取我们设置的chart图 chartIns = chart1.getReportItem().getProperty("chart.instance"); xAxis =chartIns.getAxes().get(0);            //得到x轴对象 yAxis1 = xAxis.getAssociatedAxes().get(0);        //得到y轴对象 //处理传入的参数 var sDept=params["sDept"].value;    sDept=sDept.substr(1,sDept.length-2).replace(/\'/g, '').split(","); var sDeptArr; for(var i=0;i<sDept.length;i++){ if(i!=0){    sDeptArr+=" or "; }else{    sDeptArr=""; }    sDeptArr+=" dept.dept_name like '%"+sDept[i]+"%'"; } //调用java方法,在本例中为查询学生的名字数组,用来确定折线数和与数据集中的列绑定折线(不用在意我这里写的,实际使用中换成调用你所需的java方法即可) var deptStr=getAllDept.getAllDeptById(params["projectId"].value,params["userId"].value,params["level"].value,sDeptArr,params["sLevel"].value,params["sPost"].value).split("#"); for(var i=0;i<deptStr.length;i++){ var seriesDefinit = SeriesDefinitionImpl.create();                 //生成一个SeriesDefinition对象 var lineSeries = LineSeriesImpl.create();                               //生成一个折线系列 lineSeries.getLabel().setVisible(false);//设置折线节点是否显示数值 //下面是一些我查阅api后知道的函数功能// lineSeries.getLineAttributes().setVisible(false);                //设置是否显示折线(不涉及点)// lineSeries.getLineAttributes().setColor(ColorDefinitionImpl.create(199,237,204));    //设置折线点的外框颜色// lineSeries.setCurve(true);//设置折线显示为曲线// lineSeries.getLabel().getCaption().setValue("123");//未知// lineSeries.getCaption().setValue("123"); //lineSeries.getLineAttributes().setColor(ColorDefinitionImpl.create(111,111,111));     //设置折线的颜色 var seriesTitle=deptStr[i]; var dept=i+1; //这里就是折线图与数据集列绑定的地方,如果之前数据集的列名是学生名字,那么可以通过上方调用java函数返回name数组来对应,当然如果用1,2,3来代替,就会更加方便(这里用中文貌似会出点问题,所以我用的数字) var dataStr="row[\""+dept+"\"]"; lineSeries.setSeriesIdentifier(seriesTitle);//设置折线名字 var data = QueryImpl.create(dataStr);       //得到我们选择的参数相应的数值 //data.getDefinition() 返回值 row["zwpj"] 定义 chartIns.getTitle().getLabel().getCaption().setValue("不同部门的各项能力"); //设置整幅图的标题 lineSeries.getDataDefinition().add(data)                   //把数据添加到折线里 seriesDefinit.getSeries().add(lineSeries);        //添加这个折线到SeriesDefinition对象里 yAxis1.getSeriesDefinitions().add(seriesDefinit);   }  

保存

2.调用的java函数

这里我采用了mybatis方式来获取数据,实际使用时可以根据自己使用的永久层框架来灵活变化,实际路径如下:
java script脚本中引用的包路径,函数
这里写图片描述

getAllDept.java 这个也没什么参考价值,换成自己的相应类即可,这里有一点就是如果是用spring注入的话,记得把该bean类拿出来,不然birt的js脚本获取不到的,我这里是直接调底层的myBatis来查询的,比较麻烦,不建议这样写

package com.springMVC.controller;import java.io.InputStream;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import com.report.service.deptService;public class getAllDept {//  @Autowired//  private static deptService deptService;    public static String getAllDeptById(String projectId,String userId,String level,String sDept,String sLevel,String sPost){        System.out.println("java:projectId:"+projectId);        System.out.println("userId:"+userId);        System.out.println("level:"+level);        System.out.println("sDept:"+sDept);        System.out.println("sLevel:"+sLevel);        System.out.println("sPost:"+sPost);        Map<String,String> parmas=new HashMap<String,String>();        parmas.put("projectId", projectId);        parmas.put("userId", userId);        parmas.put("level", level);        if(sDept!=null&&!"".equals(sDept)){            parmas.put("sDept", sDept);            System.out.println("sDept2:"+sDept);        }        if(sLevel!=null&&!"".equals(sLevel)){            parmas.put("sLevel", sLevel);            System.out.println("sLevel2:"+sLevel);        }        if(sPost!=null&&!"".equals(sPost)){            parmas.put("sPost", sPost);            System.out.println("sPost2:"+sPost);        }//      System.out.println(deptService);//      List<Map<String,String>> deptStr=deptService.getAllDept(parmas);        //mybatis的配置文件        String resource = "conf.xml";        //使用类加载器加载mybatis的配置文件(它也加载关联的映射文件)        InputStream is = getAllDept.class.getClassLoader().getResourceAsStream(resource);        System.out.println("is:"+is);        //构建sqlSession的工厂        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);        System.out.println("sessionFactory:"+sessionFactory);        //使用MyBatis提供的Resources类加载mybatis的配置文件(它也加载关联的映射文件)        //Reader reader = Resources.getResourceAsReader(resource);         //构建sqlSession的工厂        //SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);        //创建能执行映射文件中sql的sqlSession        SqlSession session = sessionFactory.openSession();        System.out.println("session:"+session);        /**         * 映射sql的标识字符串,         * me.gacl.mapping.userMapper是userMapper.xml文件中mapper标签的namespace属性的值,         * getUser是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL         */        String statement = "com.report.mapper.deptMapper.getAllDept";//映射sql的标识字符串        List<Map<String,String>> deptStr=session.selectList(statement, parmas);        System.out.println("deptStr:"+deptStr);        System.out.println("SIZE:"+deptStr.size());        String result="";        for(int i=0;i<deptStr.size();i++){            System.out.println(i+":"+deptStr.get(i).get("name"));            result+=deptStr.get(i).get("name")+"#";        }        System.out.println("RESULT:"+result);        return result;    }}

都完成后就可以预览下了:
这里写图片描述

大功告成