显示用于收集不同bean的报告

时间:2012-08-23 17:57:08

标签: java jasper-reports dynamic-jasper

假设我有2个豆子:

  • 员工

我将它们都添加到一个集合中。基于此集合,我想使用 JRBeanCollectionDataSource 使用 DynamicJasper 生成报告。

我能够为单个bean生成报告,但是为了收集不同的bean,我无法创建报告 - 我收到错误。

是否可以一次为两个不同的bean创建报告?

有没有其他解决方案可以解决这个问题?

2 个答案:

答案 0 :(得分:1)

根据给出的信息,它表示AwardEmployee之间没有关系。 如果是这种情况,您可以创建自定义数据源来为您处理此问题。为了完整起见,我将包括一个stubed out Award,Employee类以及一个名为MixedDataSource的自定义数据源。 (这里会列出很多代码,但坚持我一秒钟。)

<强> Award.java

package test;

public class Award {

    private String shortName;

    private String description;

    public Award(String shortName, String description) {
        super();
        this.shortName = shortName;
        this.description = description;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

<强> Employee.java

package test;

public class Employee {

    private String name;

    private String position;

    public Employee(String name, String position) {
        super();
        this.name = name;
        this.position = position;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

}

<强> MixedDataSource.java

package test;

import java.util.List;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;

@SuppressWarnings("rawtypes")//have to add this because we are not using generics
public class MixedDataSource implements JRDataSource {

    private List rows;
    private int index=0;

    public MixedDataSource(List rows) {
        super();
        this.rows = rows;
    }

    @Override
    public Object getFieldValue(JRField arg0) throws JRException {
        Object obj = rows.get(index);
        if (obj instanceof Award){
            Award row = (Award)obj;
            //now get the field name
            if (arg0.getName().equals("shortName")){
                return row.getShortName();
            } else if(arg0.getName().equals("description")){
                return row.getDescription();
            }
        } else if (obj instanceof Employee){
            Employee row = (Employee)obj;
            if (arg0.getName().equals("name")){
                return row.getName();
            } else if(arg0.getName().equals("position")){
                return row.getPosition();
            }
        }
        //means we don't know what to do with it, so just return null
        return null;
    }

    @Override
    public boolean next() throws JRException {
        //This method is used by jasper to tell us they are moving to the next row.
        //So increment the index and return true if there are still more rows, if not
        //return false
        index = index+1;
        if(index < rows.size()){
            return true;
        }
        return false;
    }

}

这可行,但可能不是你想要的方式。我的假设是奖励和员工之间存在关系,而您希望进行某种类型的分组和订购。基本上你想要在同一行上AwardEmployee。您可能希望按奖项分组并列出员工。您可能希望执行相反的操作并按员工分组并列出奖励。 如果是这种情况,请忽略上述所有内容,这是无用的。

您真正需要做的是使用您拥有的信息创建一个新的bean(我们可以称之为EmployeeAward)。如果您使用SQL查询来执行此操作,这可能非常简单,如果您使用的是hibernate,则可能需要更多工作。你基本上只是说给所有的奖项,它给你一个清单。如果您正在执行后者,则可能更容易降级到SQL或HSQL(我认为他们称之为)并手动编写查询。

所以创建一个名为EmployeeAward的类。这是我的: 包装测试;

public class EmployeeAward {


    private String employeeName;

    private String employeePosition;

    private String shortName;

    private String description;

    public EmployeeAward(String employeeName, String employeePosition,
            String shortName, String description) {
        super();
        this.employeeName = employeeName;
        this.employeePosition = employeePosition;
        this.shortName = shortName;
        this.description = description;
    }

    public EmployeeAward(Employee employee, Award award) {
        super();
        this.employeeName = employee.getName();
        this.employeePosition = employee.getPosition();
        this.shortName = award.getShortName();
        this.description = award.getDescription();
    }

    public String getEmployeeName() {
        return employeeName;
    }

    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }

    public String getEmployeePosition() {
        return employeePosition;
    }

    public void setEmployeePosition(String employeePosition) {
        this.employeePosition = employeePosition;
    }

    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }


}

现在,无论如何,您都要创建这些对象的列表,以便在那里实例化List<EmployeeAward> emplyeeAwards。此列表中的每个项目都将成为报告中的一行。现在这里是很好的部分,创建你的dataSource:

JRDataSource datasource = new JRBeanCollectionDataSource(employeeAwards);

然后像往常一样传递它,你的工作就完成了。

最后,我想说你可以用JasperReports做很多很酷的事情,但是我看到很多人都在做的事情是让它变得比它需要的更复杂。您会发现JasperReports就像我称之为平面数据源(即列表中的相同对象,列表中的每个项目都是一行等)。如果你这样做,生活会变得更轻松,更愉快。

答案 1 :(得分:0)

另一种方法是使用 SubReport 并将List<Award>传递给 MainReport ,将List<Employee>传递给 SubReport ,这样做,您可以将 SubReport 设置为 MainReport 的扩展名,例如:

MainReport: |FieldAward1|FieldAward2|FieldAward3|...|YOUR SUBREPORT HERE|

子报表: |FieldEmployee1|FieldEmployee3|FieldEmployee3|...

编辑: 即使它看起来很基本,但我必须告诉你,你应该对列表进行排序,使一个列表中的每个Object与另一个列表中的相应Object匹配。