前不久做项目的时候遇到了一个报表问题。数据源如下图所示
左上表格为主数据,点击行数据,加载右上和下方表格数据。同时下方表格拆分成两个列表展示。要求结果如下图所示
结合公司报表生成工具为Ireport5.6.0,决定使用主报表+子报表的形式实现报表
首先新建一个A4的默认报表
后续一直点击下一步,直至生成一个空白的报表文件
接下来需要添加静态文本域和参数接收
在添加文本域之前,先调整好页面,删掉不需要的页面区域
左侧列表区可以删除不需要的页面区域,也可以新增页面区域。因为我有三个子报表,需要建立三个detail区域
建立三个detail区的原因是:如果将三个子报表放入同一个detail区后,数据会显示异常,部分列表数据无法正确加载。具体原因我也不清楚,在网上找了一圈也没找到。
接下来就是对报表的非列表展示信息进行调整
新增参数
此处的参数应该和非列表展示区参数名称一一对应,且参数名一致,否则在生成报表时会提示异常。
新增子报表
子报表的生成步骤与主报表一致,生成之后,调整一下子报表的大小,使子报表充满detail区域
子报表生成之后,左侧的Parameters区域会自动新增一个SUBREPORT_DIR参数,这个参数的属性是子报表的绝对地址。
这里调整好之后,开始编辑子报表属性。编辑方式与主报表一致,删除不需要的区域,新增静态文本域以及参数文本域
因为我的子报表是列表,故具体设置如下
注意:此处参数文本域的写法是与之前的主报表的参数文本域写法不相同。 原因是二者的数据源不同,主报表的参数文本域是固定值,子报表的参数文本域是列表循环。对应的右侧的属性也不相同。可以简单的理解为Parameters对应的是不循环的数据,例如报表名称;Fields对应的是列表循环的数据,例如图中的不符合项目。
表格内容样式处理好之后,设置子报表的参数。在主报表中,新建fields参数
三个参数分别对应三个不同的子报表。关联方式是:选中子报表后,打开属性界面。
如果右侧没有属性界面,可以到上方的窗口中找到属性界面。组件面板也在此处
报表文件基本就制作完成了。但是打印的时候会出现页面空白的情况或子报表内容不展示,原因是主报表的字体设置不正确,子报表没有做正确的属性设置。报表涉及到汉字的,一般将字体设置成宋体。
除此之外,子报表的属性也要进行调整
我的子报表内容较少,选中所有控件之后,设置属性
接下来是后台数据封装 简单来说,Parameters区域用Map来存储,Fields区域用List来存储。 由于我是有子报表,故List需要嵌套一层map<String,List> 具体如下
Map<String, Object> map = Maps.newHashMap();//主表的Parameters
map.put("oldToolName", "1");
map.put("aeestNo", "1");
map.put("accuracyClass", "1");
map.put("measuringRange", "1");
map.put("expiryDate","1");
map.put("buildingUser", "1");
map.put("handlingSuggestion", "1");
List<DeviationTask> taskList = DeviationTask.me.find(qp);
List<Map> mapList1 = new ArrayList<Map>();
for (DeviationTask task : taskList) {
mapList1.add(task.toMap());
}
if (mapList1.isEmpty()) {
mapList1.add(new HashMap<>());
}
List<Map> lists = Lists.newArrayList();//主表的Fields
Map<String,Object> taskMap = Maps.newHashMap();
List<DeviationItem> itemList = DeviationItem.me.find(qp2);
List<Map> maps = Lists.newArrayList();
List<Map> maps2 = Lists.newArrayList();
for(DeviationItem item : itemList) {
Map itemMap = Maps.newHashMap();
Map itemMap2 = Maps.newHashMap();
itemMap.put("PART_NAME",item.getPartName());
itemMap.put("PART_NO", item.getPartNo());
itemMap.put("LOT_NO", item.getLotNo());
itemMap.put("DIMENSIONAL_TOLERANCE", item.getDimensionalTolerance());
itemMap.put("QUANTITY",item.getQuantity());
itemMap.put("OPERATOR", item.getOperator());
maps.add(itemMap);
itemMap2.put("NEW_TOOL_NAME", item.getNewToolName());
itemMap2.put("REINSPECTION_DESCRIPTION",item.getReinspectionDescription());
itemMap2.put("NEW_TOOL_NO", item.getNewToolNo());
itemMap2.put("RETEST_CONCLUSION", item.getRetestConclusion());
itemMap2.put("RETEST_TIME", item.getRetestTime());
itemMap2.put("RETEST_INSPECTOR", item.getRetestInspector());
maps2.add(itemMap2);
}
taskMap.put("taskList", new JRBeanCollectionDataSource(mapList1));//此处是格式化数据,否则后台会报错
taskMap.put("itemList", new JRBeanCollectionDataSource(maps));
taskMap.put("resultList", new JRBeanCollectionDataSource(maps2));
lists.add(taskMap);
String path="/jasper/qrcode/report5.jasper";//主报表文件的相对地址
String fileName="偏离校准报告";
downloadpdf(path, map, lists, fileName);
public void downloadpdf(String path,Map<String, Object> root,List<? extends Object> list,String fileName){
try {
JasperReport departJasperReport = (JasperReport) JRLoader
.loadObject(this.getClass().getResourceAsStream(path));
JasperPrint jasperPrint = JasperFillManager.fillReport(departJasperReport, root,
new JRBeanCollectionDataSource(list));
super.previewPdf(fileName);
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
SimpleOutputStreamExporterOutput simpleOs = new SimpleOutputStreamExporterOutput(
super.getResponse().getOutputStream());
exporter.setExporterOutput(simpleOs);
exporter.exportReport();
super.getResponse().getOutputStream().close();
super.renderNull();
} catch (ServiceException e) {
renderJson(new Result(false, e.getMessage()));
return;
} catch (Exception e) {
log.error("打印失败", e);
super.renderJson(new Result(false, "打印失败"));
}
}