ireport入门教程之柱形图的开发实现方法

2025-09-30 13:00:08

1、 

下面以柱状图(bar3DChart)为例,详细说明图表的开发过程。

1. 确定数据源类型和其中参数

我选择的是JRDataSourceProvider类型的数据源。我也试过JDBC数据源,没问题,只是我的应用需求是要根据用户的选择展示,所以用JRDataSourceProvider更灵活和方便些,不必每次选择都去查数据库。

用iReport开发图表,在定义图表属性中的数据时,需要添加category series,一个category series中包括series expression、category expression、Value expression、label expression等。当我开始看到这些东西时,真的时搞不明白是什么意思。试来试去,基本上弄清楚了,关键是前3个,Value expression很明白是指数据的值,category expression代表分组,series expression则代表分组中的不同指标。举例说明:我公司的一款数据产品销往全国各地的不同电信运营商,图表要按地区展示各运营商的产品套数,那么这里的地区就是category expression,运营商就是series expression,Value expression就是产品的套数了。

于是图表数据源的参数有3个就够了,即category、series和value。其他一些图表可能情况略有不同,如饼图(piechart),xylinechart等,如要做的通用些,可再加入些其他参数。我这里有3个足够了。

2、2. 开发数据源类

首先定义一个用户图表的bean:ChartDataBean,包括3个成员变量及相应的getter和setter。3个成员变量的名称如前所述,无论图表要显示什么样的数据,都按这3个变量进行对应并赋值即可。这样的名称也与iReport中图表的数据相对应,不至于搞错。如下:

public class ChartDataBean {

    String serieas;

    String category;

    float  value;

    public String getCategory() {

       return category;

    }

    public void setCategory(String category) {

       this.category = category;

    }

    public String getSerieas() {

       return serieas;

    }

    public void setSerieas(String serieas) {

       this.serieas = serieas;

    }

    public float getValue() {

       return value;

    }

    public void setValue(float value) {

       this.value = value;

    }

}

3、然后定义一个ChartDataSource类,该类应用了JRDataSource接口。该类用于在生成图表时将数据传入。如下:

public class ChartDataSource implements JRDataSource {

    private int m_nldx;

    private Vector<ChartDataBean> v;

    public ChartDataSource(){

    this(new Vector<ChartDataBean>());

    }

    public ChartDataSource(Vector<ChartDataBean> v){

    this.m_nldx=-1;

    this.v=v;

    }

    public Object getFieldValue(JRField arg0) throws JRException {

       Object o = null;

        String sName = arg0.getName();

        ChartDataBean resultset = v.elementAt(m_nldx);

        if(resultset == null)

               return null;

        if(sName.equals("serieas"))

               o =resultset.getSerieas();

        else if(sName.equals("category"))

               o = resultset.getCategory();

        else if(sName.equals("value"))

            o = resultset.getValue();

        return o;

    }

  public boolean next() throws JRException {

       // TODO Auto-generated method stub

       m_nldx ++;

        return (m_nldx < v.size());

    }

}

4、最后定义一个ChartDataSourceProvider类,该类继承类JRAbstractBeanDataSourceProvider,如下:

public class ChartDataSourceProvider extends JRAbstractBeanDataSourceProvider {

    public ChartDataSourceProvider(Class arg0) {

       super(arg0);

       // TODO Auto-generated constructor stub

    }

    public ChartDataSourceProvider() {

       super(ChartDataBean.class);

       // TODO Auto-generated constructor stub

    }

    public JRDataSource create(JasperReport arg0) throws JRException {

       // TODO Auto-generated method stub

       ChartDataSource ds=new ChartDataSource(getQueryResult());

       return ds;

    }

    public void dispose(JRDataSource arg0) throws JRException {

       // TODO Auto-generated method stub

    }

    public static Vector<ChartDataBean> getQueryResult(){

        Vector<ChartDataBean> vector = new Vector<ChartDataBean>();

        ChartDataBean result = new ChartDataBean();

        result.setCategory("北京");

        result.setSerieas("联通");

        result.setValue(1500);

        vector.addElement(result);

        result = new ChartDataBean();

        result.setCategory("北京");

        result.setSerieas("电信");

        result.setValue(1600);

        vector.addElement(result);

        result = new ChartDataBean();  

        result.setCategory("北京");

        result.setSerieas("移动");

        result.setValue(2000);

        vector.addElement(result);

        result = new ChartDataBean();   

        result.setCategory("上海");

        result.setSerieas("联通");

        result.setValue(1900);

        vector.addElement(result);

        result = new ChartDataBean();

        result.setCategory("上海");

        result.setSerieas("电信");

        result.setValue(600);

        vector.addElement(result);

        result = new ChartDataBean();

        result.setCategory("上海");

        result.setSerieas("移动");

        result.setValue(1200);

        vector.addElement(result);

        result = new ChartDataBean();

        result.setCategory("天津");

        result.setSerieas("联通");

        result.setValue(900);

        vector.addElement(result);

        result = new ChartDataBean();     

        result.setCategory("天津");

        result.setSerieas("电信");

        result.setValue(800);

        vector.addElement(result);

        result = new ChartDataBean();

        result.setCategory("天津");

        result.setSerieas("移动");

        result.setValue(1400);

        vector.addElement(result);

        return vector;

    }

}

以上getQueryResult()方法中加入了一些数据用于在iReport开发中测试预览用。实际上我认为,ChartDataSourceProvider类只是为iReport设计时从数据源中提取field信息而用的,在报表生成过程中并不会用到该类。

5、3.    图表设计

在前面工作的基础上,我们就可以利用iReport进行图表开发了。

首先新建一个报表文件,文件名最好能反应报表的内容,如bar3DChart;

然后定义报表数据源,在定义数据源前要先设置class path,通过菜单option->classpath,在classpath对话框中点击Add Folder,将你前面开发数据源类的java工程中放置编译后的.class文件的目录添加到classpath列表中,如我的是web工程,class的目录是D:\Myprj\prj1\WebRoot\WEB-INF\classes;

添加一个新数据源,通过菜单data->connection/datasource,打开connection/datasource,点击new按钮,在connection properties对话框中选择JRDataSourceProvider,点击next按钮,在新打开的对话框中有两个输入项:name和jasperreports datasource provider class。Name可任意输入,如:ChartDataSourceProvider;jasperreports datasource provider class则要输入你前面定义的ChartDataSourceProvider类,一定要输入全路径类名,和你在java工程中的包名类名一致:如com.project1.report.chart. ChartDataSourceProvider,输入完成后可点击test按钮测试一下,如弹出Connection test successful!对话框则表明数据源类添加成功,否则要检查一下classpath是否正确设置。

注:这里有个情况说明一下,如果ChartDataSourceProvider类是在iReport打开后编译的,那么即使classpath设置正确,类名输入也无问题,还是测试失败。这时就必须将iReport关闭后再打开,测试才会成功,数据源才可用,我也不知道这是为什么。这个问题在我刚开始用iReport时困扰了我一天,我新加了一个数据源,但怎么都连不通,反复检查各种设置、路径、名称、大小写等,就是不行,实在是莫名其妙呀!第二天上班,我开机后再试试,我什么都没改动,还是昨天那些东西,竟然连接成功了!我就琢磨了,是不是跟机器关开了一次有关系?机器一天都是开着的,下班才关,什么都没动,再开机问题就解决了?可也不能那么邪乎吧,什么东西做得非要重启机器?于是经过几次试验我就发现:数据源类在重新编译后,必须重新启动一次iReport。

注意要将新加的数据源设为默认。

6、读取Field,菜单file->report query打开report query对话框,在DataSource Provider属性页中点击Get fields from data source按钮,下面的列表里会出现field的列表,有serieas、category、value和class,多了个class,不去管他;点击ok;

下面设计图表了。

7、在报表title或summary band中加入一个图表工具(chart tool),在弹出的图表选择对话框中选择bar 3D,并点击ok确定。将band和图表调整至合适的大小;

双击bar 3D图表,打开bar3DChart对话框,在chart属性页中将Evaluation Time设为report(如选其他选项会出现我不想要的效果,我还没去仔细琢磨),然后点击Edit chart properties按钮,打开chart properties对话框;

8、在chart properties对话框选择Chart Data属性页,在Chart Data属性页中选择Details属性页;

点击Add按钮添加一个category series,在弹出的对话框的data属性页中有4个需要定义的表达式(expression),我们定义前3个。如Series Expression,可以通过点击右边的按钮打开表达式编辑器,在编辑器下边的objects and expression属性页中左边第一个框中选Field,然后在第二个框中双击seriesas,在上边的文本编辑区中就会出现表达式:$F{serieas}。点击应用按钮(?我的iReport中显示的是套用,我估计英文应该是apply,按咱们的习惯还是较应用吧)。其他两个表达式如法炮制,结果应该是这样的:series expression:$F{serieas}、category expression:$F{category}、Value expression:$F{value}、label expression:空白;点击ok;然后关闭chart properties对话框。

这时可以通过菜单build->execute report(Using active conn.)来预览图表了。

至此,在iReport中的图表设计工作完成。图表在web工程中的部署、载入、展现等与报表的方法是一样的。

9、4. 图表部署

我用的web服务器是tomcat5,假定web工程部署在webapps/myproject/中,在webapps/myproject/下新建一个目录reports用来放置报表文件。将前面iReport编译生成的bar3DChart.jasper文件放在该目录下。.jasper文件默认生成在iReport的安装目录下。

部署和生成报表所需的几个jar包也要放到myproject/WEB-INF/lib下,这些jar包有:jasperreports-2.0.4、iReport、jfreechart-1.0.9、jcommon-1.0.12等。版本可能不太一样。注意的是,iReport和jasperreport的图表功能实际上是用了jfreechart工具来实现的,所以一定要将jfreechart的jar包导入到工程中。

10、5. 图表的生成和展示

开发servlet。我这里以servlet方式生成图表。Servlet如下:

public class ReportServlet extends BaseHttpServlet {

    /** *  */

    public void service(

           HttpServletRequest request,

           HttpServletResponse response

           ) throws IOException, ServletException

       {

           PrintWriter out = response.getWriter();

           try                                                       

           {

              HttpSession session = request.getSession(false);

              //获得图表数据。图表数据是在其他地方查表得到并生成Vector<ChartDataBean>的数据列,然后保存在session中传递到servlet。

           Vector dataList = (Vector) session.getAttribute ("storedDataList");

    //载入图表,一定要指对路径和文件名

File reportFile = new File(context.getRealPath ("/reports/bar3DChart.jasper"));

if (!reportFile.exists())

                throw new JRRuntimeException("File WebappReport.jasper not found. The report design must be compiled first.");

JasperReport jasperReport = (JasperReport)JRLoader.loadObject(reportFile.getPath());

//图表的参数,及ireport中的定义变量,如报表标题、图表日期等,也是于他处设置保存在session中

Map parameters =(Map)session.getAttribute

                                     ("jasper_parameters");   //这里导入图表数据,并生成报表

JasperPrint jasperPrint =

                JasperFillManager.fillReport(

                   jasperReport,

                   parameters,

                   new ChartDataSource(dataList)

                   );

//JasperPrint jasperPrint =(JasperPrint)session.getAttribute

//(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE);

//注:以上的步骤实际上都可以在他处完成,最后将jasperPrint保存到session中,这样在servlet中只需从session中取得jasperPrint即可(如上面注释掉的这条语句),可以将servlet做成通用的类来展示输出所有的报表。

//输出html 用JRHtmlExporter

    JRHtmlExporter exporter = new JRHtmlExporter();

              Map imagesMap = new HashMap();

              response.setContentType("text/html");

                request.getSession().setAttribute("IMAGES_MAP", imagesMap);       request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);

                  exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);

              exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);

                  exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap);                            exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,"image?image=");               exporter.setParameter(JRHtmlExporterParameter.BETWEEN_PAGES_HTML, "");

    exporter.exportReport();

}

           catch (JRException e)

           {

              out.println("<html>");

              out.println("<head>");

              out.println("<title>JasperReports - Web Application Sample</title>");

              out.println("<link rel=\"stylesheet\" type=\"text/css\" href=\"../stylesheet.css\" title=\"Style\">");

              out.println("</head>");    

              out.println("<body bgcolor=\"white\">");

              out.println("<span class=\"bnew\">JasperReports encountered this error :</span>");

              out.println("<pre>");

              e.printStackTrace();

              out.println("</pre>");

              out.println("</body>");

              out.println("</html>");

           }

       }

 6. 添加servlet映射

在web.xml中添加如下设置:

<servlet>

       <servlet-name>ReportServlet</servlet-name>

       <servlet-class>com.project1.report.ReportServlet </servlet-class>

    </servlet>

    <servlet>

       <servlet-name>ImageServlet</servlet-name>      <servlet-class>net.sf.jasperreports.j2ee.servlets.ImageServlet</servlet-class>

    </servlet>

<servlet-mapping>

    <servlet-name>ImageServlet</servlet-name>

    <url-pattern>/image</url-pattern>

  </servlet-mapping>

  <servlet-mapping>

       <servlet-name>ReportServlet</servlet-name>

       <url-pattern>/ReportServlet</url-pattern>

    </servlet-mapping>

ImageServlet干嘛用的?注意到ReportServlet的代码中有这么一句:

exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI,"image?image=");

ImageServlet就是为这句而来的,html方式输出报表时要用到的小图标就在这里,如果没有ImageServlet或设置不对,你可以看看输出的报表是什么样的,尽是红叉叉!

11、同为比较常用的java报表生成工具,FineReport对柱状图的解决方案和实现方法与ireport有所不同,具体实现思路和步骤如下,供ireport使用者借鉴:

12、在FineReport中,图表有两种插入方式:作为单元格元素插入或者作为悬浮元素插入,以下是用两种思路实现柱形图的过程:

13、单元格图表

1. 描述

如下图,每一组都跟随有一个统计图直观的查看该组的数据情况,可以使用单元格图表实现这样的可扩展的效果效果。

·         单元格图表的优势

图表作为单元格元素插入到报表中,就可以通过单元格的父子关系,跟随主格的扩展自动生成相应的图表,而不需要对每组数据单独制作对应的图表。

ireport入门教程之柱形图的开发实现方法

14、2. 示例

以下我们详细介绍上图中跟随扩展的图表制作步骤。

15、2.1 数据准备

打开报表%FR_HOME%\WebReport\WEB-INF\reportlets\doc\Primary\GroupReport\Group.cpt。在地区销量分组报表的基础上添加图表,实现每个地区有一张销量统计图。

这边扩展出来的每张图表只显示当前地区的数据,因此不能直接将数据集作为图表数据来源(数据集是取出销量表中的所有数据),只能使用报表中单元格数据。

注:单元格元素图表与单元格数据源图表不是一个概念,单元格元素图表是指图表插入方式为单元格,可跟随单元格扩展,拥有单元格的一些属性,而单元格数据源图表是指图表绑定数据的时候绑定的是单元格数据,而非数据集数据。

16、2.2 插入单元格图表

合并第二行后面的一片区域,右击单元格单元格元素>插入图表>柱形图,点击确定。

ireport入门教程之柱形图的开发实现方法

17、2.3 设置图表数据

设置图表数据如下图,每个销售员的销量图,点击完成:

ireport入门教程之柱形图的开发实现方法

18、2.4 设置图表父格

由父子格概念可知,图表所在单元格默认以销售员数据列为父格,扩展出的每个销售员都会对应有一张图表;

而这里我们只需要扩展出来的每个地区跟随一张图表,因此需要设置图表所在单元格为地区单元格。

19、2.5 保存并预览

保存模板并分页预览,便可以看到上图效果了

20、悬浮元素图表

图表还可以作为悬浮元素插入到报表中。

·         悬浮图表的优势

作为悬浮元素插入到报表中的图表,没有单元格的限制,可以图表位置固定,也可以随意拖放到任何位置,大小设置后不会改变,没有父格,不会因为其他单元格的扩展而受影响。

悬浮图表的定义与单元格图表是基本上完全相同的,只是在第一步插入图表的时候,选择掺入悬浮元素即可,这里就不重复介绍了,可以看到,可以随意拖动图表及改变图表大小,操作方便,如下图:

ireport入门教程之柱形图的开发实现方法

21、注:悬浮元素做出来的图表不同于上一节单元格图表,能根据父格进行数据过滤,进行扩展从而根据地区显示对应的柱形图,悬浮元素没有父格概念一说,故,其不能通过设置父格来进行数据过滤,进行扩展,添加了几个悬浮元素图表,最后在web端查看的时候只会显示几个图表。

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢