假设我有2个豆子:
我将它们都添加到一个集合中。基于此集合,我想使用 JRBeanCollectionDataSource 使用 DynamicJasper 生成报告。
我能够为单个bean生成报告,但是为了收集不同的bean,我无法创建报告 - 我收到错误。
是否可以一次为两个不同的bean创建报告?
有没有其他解决方案可以解决这个问题?
答案 0 :(得分:1)
根据给出的信息,它表示Award
和Employee
之间没有关系。
如果是这种情况,您可以创建自定义数据源来为您处理此问题。为了完整起见,我将包括一个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;
}
}
这可行,但可能不是你想要的方式。我的假设是奖励和员工之间存在关系,而您希望进行某种类型的分组和订购。基本上你想要在同一行上Award
和Employee
。您可能希望按奖项分组并列出员工。您可能希望执行相反的操作并按员工分组并列出奖励。 如果是这种情况,请忽略上述所有内容,这是无用的。
您真正需要做的是使用您拥有的信息创建一个新的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匹配。