java Jasper Reports:如何编译子报表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10004800/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Jasper Reports: How to compile subreports
提问by Numeron
I have a standalone application, and one of its duties is to take the path of a *.jrxml file and compile it.
我有一个独立的应用程序,它的职责之一是获取 *.jrxml 文件的路径并编译它。
I can do this without problem until a report with a subreport comes up, where the compilation of the master does not compile any of its children, resulting in a subreport *.jasper file not found later down the track.
我可以毫无问题地执行此操作,直到出现带有子报告的报告,其中主程序的编译不会编译其任何子报告,从而导致稍后找不到子报告 *.jasper 文件。
Is there any way to
有没有什么办法
1) Set the JasperCompileManager to automatically pick up subreports?
1) 设置 JasperCompileManager 自动拾取子报表?
2) Get a list of paths to subreports contained within either a JasperDesign or JasperReport object?
2) 获取包含在 JasperDesign 或 JasperReport 对象中的子报表的路径列表?
I have no direct access to the jrxml files, so modifying the reports to suit the compile method is not an option, nor is applying any standard naming scheme to infer which subreports belong to which reports.
我无法直接访问 jrxml 文件,因此修改报告以适合编译方法不是一个选项,也不是应用任何标准命名方案来推断哪些子报告属于哪些报告。
There is a similar problem here:
这里有一个类似的问题:
http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=40683
http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=40683
where a JRVisitor is used to produce a list of JRSubreport objects, however there is no explanation of how to use this to get a path to the subreport in order to compile it and recursively look for subreports of subreports, and I cant figure it out.
其中 JRVisitor 用于生成 JRSubreport 对象列表,但是没有说明如何使用它来获取子报表的路径以便编译它并递归查找子报表的子报表,我无法弄清楚。
回答by Numeron
Ok, so it required a bit of hackery, but I was able to figure something out...
好的,所以它需要一点技巧,但我能够想出一些办法......
The subreport.getExpression().getText() returns the expression field of the subreport widget thing in the master report, and is a string that looks something like this
subreport.getExpression().getText() 返回主报表中子报表小部件事物的表达式字段,并且是一个看起来像这样的字符串
$P{SUBREPORT_DIR} + "/report_sub1.jasper"
So I was able to pull it apart to get the name using the following. Its not ideal, but it should hold up.
因此,我能够将其拆开以使用以下内容获得名称。它并不理想,但它应该坚持下去。
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 subreports of subreports etc. Not perfect, but good enough for my app. All compiled *.jasper files are saved back onto disk in the same location as the uncompiled *.jrxml files were picked up, but this wouldn't be hard to change. The compiled main report object is passed back incase you want to run it or whatever.
这是我的整个 compileReport 方法,演示如何递归编译子报表等的子报表。不完美,但对我的应用程序来说已经足够了。所有已编译的 *.jasper 文件都保存回磁盘上与未编译的 *.jrxml 文件相同的位置,但这并不难改变。编译后的主报告对象被传回,以防您想运行它或其他任何东西。
Remember that this code is 9 months old at the time of this edit, and newer versions of Jasper Reports may now have an inbuild functions for this kind of thing.
请记住,此代码在进行此编辑时已有 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;
}