Jasper Reports: How to Compile Subreports

I have a separate application, and one of his duties is to take the path to the * .jrxml file and compile it.

I can do this without problems until a report with a subtitle appears, where compiling the wizard will not compile any of its children, resulting in a subreport * .jasper file not found later on the track.

Is there any way

1) Install JasperCompileManager to automatically receive subscriptions?

2) Get a list of paths for subscriptions contained in a JasperDesign or JasperReport object?

I do not have direct access to jrxml files, so changing reports according to the compilation method is not an option and does not use any standard naming scheme to conclude which subordinate records belong to which reports.

There is a similar problem here:

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

where JRVisitor is used to create a list of JRSubreport objects, however there is no explanation of how to use this to get the subheading path, to compile it and recursively search for the subheadings of nested reports, and I cannot figure it out.

+8
java jasper-reports reporting report
source share
1 answer

Okay, so it took a few hackers, but I was able to figure something out ...

Subreport.getExpression (). getText () returns the expression field of the subreport widget object in the main report and is a string that looks something like this:

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

So, I was able to split it to get the name using the following. This is not ideal, but it should be delayed.

 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); } } 

EDIT:

Here is my whole compileReport method demonstrating how to recursively compile nested reports in subheadings, etc. Not perfect, but good enough for my application. All compiled * .jasper files are saved back to disk in the same place where the files were collected without compiling * .jrxml, but this will not be difficult to change. The compiled main report object is passed back if you want to run it or something else.

Remember that during this editing, this code is 9 months old, and newer versions of Jasper reports can now have built-in functions for this kind of thing.

 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; } 
+8
source share

All Articles