假设我有 2 个 bean:
- 奖
- 员工
我将它们都添加到一个集合中。基于此集合,我想使用JRBeanCollectionDataSource使用DynamicJasper生成报告。
我能够为单个 bean 生成报告,但是对于不同 bean 的集合,我无法创建报告 - 我收到错误消息。
是否可以一次为两个不同的 bean 创建报告?
是否有任何替代解决方案来解决此任务?
假设我有 2 个 bean:
我将它们都添加到一个集合中。基于此集合,我想使用JRBeanCollectionDataSource使用DynamicJasper生成报告。
我能够为单个 bean 生成报告,但是对于不同 bean 的集合,我无法创建报告 - 我收到错误消息。
是否可以一次为两个不同的 bean 创建报告?
是否有任何替代解决方案来解决此任务?
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 之间存在关系,并且您想要进行某种类型的分组和排序。本质上你想要一个Award
和Employee
在同一行。您可能希望按奖项分组并列出员工。您可能想做相反的事情,按员工分组并列出奖项。如果是这样,请忽略以上所有内容,这是没有用的。
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 就像我所说的平面数据源(即列表中的相同对象,列表中的每个项目都是一行等)。如果你这样做,生活会变得更轻松,更愉快。
另一种方法是使用SubReport并将 传递List<Award>
给MainReport和传递List<Employee>
给SubReport,这样做,您可以将SubReport设置为MainReport的扩展,例如:
主报告:
|FieldAward1|FieldAward2|FieldAward3|...|YOUR SUBREPORT HERE|
子报告:
|FieldEmployee1|FieldEmployee3|FieldEmployee3|...
编辑:即使它看起来很基本,我也必须告诉你,你应该对列表进行排序,以使一个列表中的每个对象与另一个列表中的相应对象匹配。