3

假设我有 2 个 bean:

  • 员工

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

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

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

是否有任何替代解决方案来解决此任务?

4

2 回答 2

1

Award根据给出的信息,这意味着和之间没有关系Employee。如果是这种情况,您可以创建一个自定义数据源来为您处理。为了完整起见,我将包含一个已删除的 Award 和 Employee 类以及一个名为 MixedDataSource 的自定义数据源。(这里会列出很多代码,但请稍等片刻)。

奖励.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;
    }
}

雇员.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;
    }

}

混合数据源.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;
    }

}

这会起作用,但可能不是您想要的方式。我的假设是 Award 和 Employee 之间存在关系,并且您想要进行某种类型的分组和排序。本质上你想要一个AwardEmployee在同一行。您可能希望按奖项分组并列出员工。您可能想做相反的事情,按员工分组并列出奖项。如果是这样,请忽略以上所有内容,这是没有用的。

EmployeeAward您真正需要做的是使用您拥有的信息创建一个新的 bean(我们可以称之为 bean )。如果您使用 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实例化。此列表中的每个项目都将成为报告中的一行。现在这是很好的部分,创建您的数据源:

JRDataSource datasource = new JRBeanCollectionDataSource(employeeAwards);

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

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

于 2012-08-24T19:59:40.747 回答
0

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

主报告: |FieldAward1|FieldAward2|FieldAward3|...|YOUR SUBREPORT HERE|

子报告: |FieldEmployee1|FieldEmployee3|FieldEmployee3|...

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

于 2012-08-23T20:25:41.680 回答