Jasper Reports:如何编译子报告

我有一个独立的应用程序,其职责之一是获取* .jrxml文件的路径并进行编译。

我可以毫无问题地执行此操作,直到出现具有子报表的报表,其中主程序的编译不会编译其任何子项,从而导致稍后在轨道中找不到子报表* .jasper文件。

有什么办法吗?

1)设置JasperCompileManager以自动获取子报告?

2)获取JasperDesign或JasperReport对象中包含的子报告的路径列表?

我无法直接访问jrxml文件,因此修改报告以适应编译方法不是一种选择,也不应用任何标准命名方案来推断哪些子报告属于哪些报告。

这里有一个类似的问题:

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

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

好的,所以它需要一些hackery,但我能够找出一些东西……

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 completedSubReports = new ArrayList(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; }