1.1 为什么要自定义数据源
简单的报表,当然用不着自定义数据源,直接在JasperReports里编写SQL就可以了。
但查询复杂起来时,还死守着一条SQL写完会让SQL变得又长又难读,从来都最讨厌 别人在SQL上炫技。这时候,在JasperReport外部的Java程序里进行数据的采集(还可以进一步把相近的查询封装到一个数据采集类中),把结果通过自定义数据源传入JasperReports,而JasperReport只负责数据的显示,更符合数据与显示分开这个普适的模式。
搞定了可分解重用的数据源后,我才真正敢把JasperReports用到系统上。否则,无法想象怎么在JasperReport文件里维护那么多的SQL.
1.2 自定义数据源的机制
dori.jasper.engine.JRDataSource 接口非常简单,只要实现两个方法:
public boolean next() throws JRException;
public Object getFieldValue(JRField jrField) throws JRException;
1.3 Sample代码与解释
//封装了大量查询的reporter类
MooncakeReporter mooncakeReporter = new MooncakeReporter();
//建立VO的Map,因为需要多次执行查询,需要快速找回VO来赋值,因此采用Map.
Map map = new HashMap();
rs = mooncakeReporter.findAllVaildProduct();
while (rs.next())
{
MooncakeVO mooncakeVO = new MooncakeVO();
String goods_no = rs.getString("goods_no");
String goods_name = rs.getString("name");
mooncakeVO.setName(goods_name);
mooncakeVO.setCode(code);map.put(goods_no, mooncakeVO);
}
//调用Reporter封装好的查询函数获取数据,并通过主键goods_no获得VO来赋值。
rs = mooncakeReporter.findSaleOrderByShopType("shop");
while (rs.next())
{
String goods_no = rs.getString("goods_no");
MooncakeVO mooncakeVO = (MooncakeVO) map.get(goods_no);
if (mooncakeVO != null)
{
mooncakeVO.setShopCount(new Integer(rs.getInt("count")));
}
}
//如此重复执行查询若干步
.....
//因为JRBeanCollectionDataSource需要Collection或者Array,把Map转化为List。
List result = new ArrayList(map.values());
//对result进行排序,通过BeanUtils的beanComparator来实现,在下一小节会讲到。
Collections.sort(result, new BeanComparator("code"));
//最后把result赋给JRBeanCollectionDataSource
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters,
new JRBeanCollectionDataSource(result));
1.4 扩展
1.用BeanComparator进行排序
用map来存放的VO是没有顺序的,必须对其进行排序。 用jakata commons-beanutils的BeanComparator类,可以动态改变排序的列,比自己实现Compare()接口好。
Collections.sort(result, new BeanComparator("code"));对于"Order by lastName, firstName"的情形,还可以写成这样,其中ComparatorChain属于jakata commons-collections包。
ArrayList sortFields = new ArrayList();
sortFields.add(new BeanComparator("lastName"));
sortFields.add(new BeanComparator("firstName"));
ComparatorChain multiSort = new ComparatorChain(sortFields);
Collections.sort(rows,multiSort);
2.<box>元素, 终于不用手工划表格线了
iReports终于出了0.41版, 支持 JasperReports 0.64。
为什么这么重要呢? 因为从0.63开始,JasperReports支持了千呼万唤始出来的box属性,可以像其他商业报表工具那样,设置表格的四周是否有线。而在以前,虽然人人都说神仙好,但一想起要手工划表格线,还要精确的在两个field之间在留1个像素,头皮就一阵阵发麻。
另外,新的box在excel下也表现良好,不再需要为Html和Excel制作两个不同的模版文件.
3.iReport报表的快速设计
一开始什么都不懂,对着满屏的元素,拖拉半天才把它对齐,差点就用不下去了。 3.2 批量修改元素属性
和很多网页编辑器一样,可以同时选择多个元素然后点选属性批量修改。
3.3 iReport,UltraEdit双管齐下修改报表变量
当变量比较多时,用Ultraedit直接Copy Paste就要比用iReport来增加filed和varible快很多。
4.导出Excel文件
刚开始导出的Excel文件叫人无比失望,一个交得出去的Excel文件起码应该:
1.所有的Field要撑满所在Band的高度,不要留空隙
2.所有对象选成透明Transparent
3.设置参数
exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
Boolean.TRUE);
exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,
Boolean.FALSE);
5.1 输出GBK字符集
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "GBK");5 .2 定义filed显示的Pattern
5.3 Expresstion用三目运算符实现简单的if-else选择
有些情况比如分母不能为0的判断,可以用三目运算符搞定,不一定要劳烦VO来计算。
5.4 批量编译文件
ireport的Plug-in里有批量编译目录下所有文件的命令
江南白衣