《jasperreport 自定义javaBean数据源》
一:说明:
1.目前公司要做一类报表,统计要求显示从1月份到12月份的所有数据。且每个月份的数据列头都是一样的。见图:
2.由于用户运行环境要求,我们的报表数据源只能采用javabean的方式。
3.报表模块设计。
由于我们使用ireport设计报表模板,所以报表的列头,是不能通过循环生成的(即循环从1月到12月的列头),只能通过画出1月到12月的列头。见图:
二:实现生成报表:
1.普通的做法是。定义一个javaben类,包含从1月到12月份的所有字段。eg:
public class RepProjectStockModeSumReport extends BaseObject implements java.io.Serializable {
private String stockMode; //采购模式
private Double stockNumber1; //数量
private Double paStockPrice1; //平安采购价格
private Double marketPrice1; //市场价格
private Double marketSaveMoney1; //节约金额
private Double marketSaveMoneyPer1; //节约比例
private Double stockNumber2; //
private Double paStockPrice2; //
private Double marketPrice2; //
private Double marketSaveMoney2; //
private Double marketSaveMoneyPer2; //
}
每一行就是一个model记录。
这个是比较常用,比较简单的做法,也可以说是最稳定的做法。一般情况下,我们应该用它,除非你是跟我一样,不着实际的人。
2.我的做法:
public class RepProjectStockModeSumReport extends BaseObject implements java.io.Serializable {
private String stockMode; //采购模式
private Double stockNumber; //数量
private Double paStockPrice; //平安采购价格
private Double marketPrice; //市场价格
private Double marketSaveMoney; //节约金额
private Double marketSaveMoneyPer; //节约比例
}
即只列出一月份的属性,每个实体代表每个月份下的一行数据。
及一行下存在多条model数据。
三:自定义javabean数据源:
自定义javabean数据源很简单,只需要继承extends JRAbstractBeanDataSource就行了,同时实现next()和getFieldValue方法。
通过在自定义的javabean数据源中,指定获取当前显示数据的规则,从而决定当前显示那一条model数据。
eg:
public class PaAnCustomJRdataSource extends JRAbstractBeanDataSource {
private Collection<ItemStatReport> data;
private Object currentBean;
private Iterator<ItemStatReport> iterator;
private List<ItemStatReport> allData;
private int index = -1;
public PaAnCustomJRdataSource(Collection<ItemStatReport> collection) {
super(true);
if (collection.size() > 0) {
this.allData = (List<ItemStatReport>) collection;
List<ItemStatReport> list = (List<ItemStatReport>) collection;
Collections.sort(list, new Comparator<ItemStatReport>() {
public int compare(ItemStatReport o1, ItemStatReport o2) {
return o1.getSeqNumber() - o2.getSeqNumber();
}
});
List<ItemStatReport> dataList = new ArrayList<ItemStatReport>();
ItemStatReport itmesr = list.get(0);
int seqNumber = itmesr.getSeqNumber();
for (ItemStatReport isr : allData) {
if (isr.getSeqNumber() == seqNumber) {
dataList.add(isr);
} else {
break;
}
}
this.data = dataList;
this.iterator = data.iterator();
}
}
public boolean next() {
index++;
boolean hasNext = false;
if (this.iterator != null) {
hasNext = this.iterator.hasNext();
if (hasNext) {
this.currentBean = this.iterator.next();
}
}
return hasNext;
}
public Object getFieldValue(JRField field) throws JRException {
Object value = null;
String fieldName = field.getName();
String[] arr = fieldName.split("_");
if (arr.length > 1) {
int seqNumber = Integer.parseInt(arr[1]);
int dataLength = this.data.size();
int inteNumber = (seqNumber * dataLength) + this.index;
ItemStatReport positionObj = this.allData.get(inteNumber);
ItemStatReport currentObj = (ItemStatReport) currentBean;
if (currentObj.getCompareCol().intValue() == positionObj.getCompareCol().intValue()) {
value = getFieldValue(positionObj, field);
} else {
throw new RuntimeException("no found target Object !");
}
} else {
value = getFieldValue(currentBean, field);
}
return value;
}
}
public class PaAnCustomOfTwolJRdataSource extends JRAbstractBeanDataSource {
private Collection<ItemStatReport> data;
private Object currentBean;
private Iterator<ItemStatReport> iterator;
private List<ItemStatReport> allData;
private List<ItemStatReport> secondData;//二级数据源
private Integer currParentVal;
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
protected Integer initialValue() {
return 0;
}
};//保存线程变量
public PaAnCustomOfTwolJRdataSource(Collection<ItemStatReport> collection, Integer parentVal1) {
super(true);
this.currParentVal = parentVal1;
int length = collection.size();
if (length > 0) {
this.allData = (List<ItemStatReport>) collection;
List<ItemStatReport> dataList = new ArrayList<ItemStatReport>();
List<ItemStatReport> data = new ArrayList<ItemStatReport>();
//FIXME :加入排序方法
//TODO:加入获取数据源的算法。
int count = threadLocal.get();
int j = count;
for (; j < length; j++) {
ItemStatReport itemSr = allData.get(j);
Integer com1 = itemSr.getCompareCol1();
if (com1 != null && com1.intValue() == parentVal1.intValue()) {
dataList.add(itemSr);
count++;
} else {
break;
}
}
//reset variable count
if (count == length) {
count = 0;
}
threadLocal.set(new Integer(count));
//确定报表的行数。
for (int i = 0; i < dataList.size(); i += 13) {
ItemStatReport isr = dataList.get(i);
data.add(isr);
}
this.data = data;
this.secondData = dataList;
this.iterator = data.iterator();
}
}
public boolean next() {
boolean hasNext = false;
if (this.iterator != null) {
hasNext = this.iterator.hasNext();
if (hasNext) {
this.currentBean = this.iterator.next();
}
}
return hasNext;
}
public Object getFieldValue(JRField field) throws JRException {
Object value = null;
String fieldName = field.getName();
ItemStatReport currentObj = (ItemStatReport) currentBean;
String[] arr = fieldName.split("_");
if (arr.length > 1) {
int seqNumber = Integer.parseInt(arr[1]);
ItemStatReport positionObj = null;
for (ItemStatReport isr : secondData) {
if (isr.getSeqNumber() == seqNumber && currentObj.getCompareCol().intValue() == isr.getCompareCol().intValue()) {
positionObj = isr;
break;
}
}
if (positionObj == null) {
throw new RuntimeException("no found target data !");
}
value = getFieldValue(positionObj, field);
} else {
value = getFieldValue(currentBean, field);
}
return value;
}
}
这是我继承的两个JRAbstractBeanDataSource。