【问题标题】:Jasper Reports: How to compile subreportsJasper 报告:如何编译子报告
【发布时间】:2012-04-04 04:09:41
【问题描述】:

我有一个独立的应用程序,它的职责之一是获取 *.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 文件,而不是即时编译它。 :(
  • 类似问题已解决,但未在磁盘上保存文件:stackoverflow.com/questions/9785451/…

标签: java jasper-reports reporting report


【解决方案1】:

好的,所以它需要一些技巧,但我能够弄清楚一些事情......

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() 是做什么的?子报表的编译结果存储在哪里?在磁盘上?
  • 我知道它有大约 2 年的历史。但是这个答案对我来说就像魅力一样。谢谢
  • 类名在哪里?我们应该在哪里分配那个类?是在运行时还是在编译时?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多