2012-10-06

使用 Java 輸出資料到 JasperReports 子報表表身(Subreport Detail)

前面講過 使用 Java 輸出資料到 Jasperreports 主報表表身(Detail),再來看看丟資料給子報表。

拉報表
  • 建立空白主報表。
  • 新增兩個從 Java 傳進來的 Parameter

    • LIST,型別為 net.sf.jasperreports.engine.data.JRMapCollectionDataSource,作為子報表Detail 的資料來源。
    • SUB_REPORT,型別為 net.sf.jasperreports.engine.JasperReport。



  • 從調色板將 Subreport 拉到 Detail 裡,彈出 Subreport Wizard,選擇「Create a new report」,一直按下一步到最後一頁「Connection exp」,勾選「Use a JRDatasource expression」,輸入「$P{LIST}」,這就是剛建立的 parameter。


  • 完成後會先跳到子報表,這時先回到主報表繼續做設定,可以在 Designer 看到 Subreport 元件,這邊的尺寸不重要,一定會依 Subreport 實際的內容佔滿需要的空間。

  • 再來修改 Subreport 的屬性,將 Subreport Expression 修改為 $P{SUB_REPORT},也就是最前面建立的第二個 parameter,再將 Expression Class 修改為 net.sf.jasperreports.engine.JasperReport。

  • 切換到子報表,像 使用 Java 輸出資料到 Jasperreports 主報表表身(Detail) 所說的建立三個 field,並指明型別,需與 Java 程式一致。





  • 再將三個 field 拉到 Designer 裡排排站。


  • 完成後編譯主報表與子報表,得到兩個 jasper 檔後,就可以開始寫程式了。

Java 程式

和一般沒有子報表的程式差別在於,新增子報表並塞到主報表的參數裡,其餘都一樣。
String mrFile = "D:/_Download/report6.jasper";
String srFile = "D:/_Download/report6_subreport1.jasper";
String outFile = "D:/_Download/report6j.pdf";
try {
  Map<String, Object> parameters = new HashMap<String, Object>();

  // 讀入子報表,並塞到主報表的參數裡
  JasperReport subreport = (JasperReport) JRLoader.loadObjectFromFile(srFile);
  parameters.put("SUB_REPORT", subreport);

  // Map 表示一筆資料,再用 List 裝起來,表示所有資料
  Collection<Map<String, ?>> list = new ArrayList<Map<String, ?>>();
  // 塞入測試資料
  for (int i = 0; i < 20; i++) {
    Map<String, Object> data = new HashMap<String, Object>();
    data.put("id", new BigDecimal(i + 1));
    data.put("title", "中文 字串 String " + i);
    data.put("date", new Date(112, 9, i + 1));
    list.add(data);
  }
  // 使用 JRMapCollectionDataSource 打包資料成 JRDataSource 介面
  // 子報表的 data 一樣塞到主報表的參數裡
  parameters.put("LIST", new JRMapCollectionDataSource(list));

  // 產出報表
  JasperPrint print = JasperFillManager.fillReport(mrFile, parameters, new JREmptyDataSource());
  JRExporter exporter = new JRPdfExporter();
  exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, outFile);
  exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
  exporter.exportReport();
}
catch (JRException e) {
  e.printStackTrace();
}
噹,收工。

其實有一個很有趣的地方,Jasperreports 的子報表其實也是一張可以獨當一面的報表,換句話說,任何報表都是可以作為子報表的。
---
---
---

1 則留言:


  1. 現在開源報表軟件大勢已去,沒有好的技術支持,時間成本和學習成本太高,不如直接買一個合適的商業報表
    而且在功能上面也不如商業報表,比如jasperreport和finereport的對比:
    http://www.finereport.com/tw/knowledge/acquire/jasperreportsireport.html

    回覆刪除