Jasper Reports:如何编译子报表

8
我有一个独立应用程序,其中之一的职责是获取*.jrxml文件路径并编译它。在没有子报表的情况下,我可以毫无问题地完成此操作,但当出现一个包含子报表的报表时,主报表的编译不会编译任何子报表,结果后续找不到一个子报表*.jasper文件。是否有任何方法:
1)设置JasperCompileManager自动获取子报表?
2)获取包含在JasperDesign或JasperReport对象中的子报表路径列表?
我无法直接访问jrxml文件,因此修改报告以适应编译方法不是选项,也不是应用任何标准命名方案来推断哪些子报告属于哪些报告。
这里存在类似的问题:

http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=40683

在使用JRVisitor生成JRSubreport对象列表时,没有解释如何使用它来获取子报表的路径以便编译它并递归地查找子报表的子报表,我无法弄清楚。


我也想听答案。我最终直接链接到子报告的*.jasper文件,而不是动态编译它。 :( - Rangi Lin
类似的问题可以在不将文件保存到磁盘的情况下解决:https://dev59.com/7Gkw5IYBdhLWcg3wlrka - Lukasz Stelmach
1个回答

11

好的,所以需要一些技巧才行,但我能够想出一个解决方案...

subreport.getExpression().getText() 返回主报表中子报表小部件的表达式字段,是一个类似于以下内容的字符串

$P{SUBREPORT_DIR} + "/report_sub1.jasper"

所以我使用以下方法将其拆开,以获取名称。虽然不理想,但应该能够解决问题。

JRElementsVisitor.visitReport(jasperReport, new JRVisitor(){

  // ** snip other overrides **

  @Override
  public void visitSubreport(JRSubreport subreport){
    String expression = subreport.getExpression().getText().replace(".jasper", ".jrxml");
    StringTokenizer st = new StringTokenizer(expression, "\"/");
    String subreportName = null;
    while(st.hasMoreTokens())
      subreportName = st.nextToken();
    compileReport(subreportName);
  }
}

编辑:

这里是我的 compileReport 方法的完整代码,演示了如何递归地编译子报表和子报表等。并不完美,但足以满足我的应用程序需求。所有编译好的 *.jasper 文件都保存回磁盘,位置与获取未编译的 *.jrxml 文件的位置相同,但这很容易更改。已编译的主报表对象被传回,以防您想要运行它或其他操作。

请记住,此代码在进行编辑时已有9个月之久,而 Jasper Reports 的新版本现在可能已经具有内置的这种功能。

private static final String reportsPath = "someplace/nice/";
private ArrayList<String>   completedSubReports = new ArrayList<String>(30);
private Throwable           subReportException  = null;

/**
 * Recursively compile report and subreports
 */
public JasperReport compileReport(String reportName) throws Throwable{
  JasperDesign jasperDesign = JRXmlLoader.load(reportsPath + reportName + ".jrxml");
  JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
  JRSaver.saveObject(jasperReport, reportsPath + reportName + ".jasper");
  toLog("Saving compiled report to: " + reportsPath + reportName + ".jasper");
  //Compile sub reports
  JRElementsVisitor.visitReport(jasperReport, new JRVisitor(){
    @Override
    public void visitBreak(JRBreak breakElement){}

    @Override
    public void visitChart(JRChart chart){}

    @Override
    public void visitCrosstab(JRCrosstab crosstab){}

    @Override
    public void visitElementGroup(JRElementGroup elementGroup){}

    @Override
    public void visitEllipse(JREllipse ellipse){}

    @Override
    public void visitFrame(JRFrame frame){}

    @Override
    public void visitImage(JRImage image){}

    @Override
    public void visitLine(JRLine line){}

    @Override
    public void visitRectangle(JRRectangle rectangle){}

    @Override
    public void visitStaticText(JRStaticText staticText){}

    @Override
    public void visitSubreport(JRSubreport subreport){
      try{
        String expression = subreport.getExpression().getText().replace(".jasper", "");
        StringTokenizer st = new StringTokenizer(expression, "\"/");
        String subReportName = null;
        while(st.hasMoreTokens())
          subReportName = st.nextToken();
        //Sometimes the same subreport can be used multiple times, but
        //there is no need to compile multiple times
        if(completedSubReports.contains(subReportName)) return;
        completedSubReports.add(subReportName);
        compileReport(subReportName);
      }
      catch(Throwable e){
        subReportException = e;
      }
    }
    @Override
    public void visitTextField(JRTextField textField){}

    @Override
    public void visitComponentElement(JRComponentElement componentElement){}

    @Override
    public void visitGenericElement(JRGenericElement element){}
  });
  if(subReportException != null) throw new RuntimeException(subReportException);
  return jasperReport;
}

compileReport()函数是用来做什么的?子报表编译的结果存储在哪里?在磁盘上吗? - dzieciou
我知道这个回答大约有2年的历史了,但是它对我非常有效。谢谢! - Alfredo A.
类的名称在哪里?我们应该在哪里分配这个类?是在运行时还是编译时? - Lucke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接