Num*_*ron 8 java reporting report jasper-reports
我有一个独立的应用程序,其职责之一是获取*.jrxml文件的路径并进行编译.
我可以毫无问题地执行此操作,直到带有子报表的报表出现,其中master的编译不会编译其子任务,从而导致稍后在轨道下找不到子报表*.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"
Run Code Online (Sandbox Code Playgroud)
所以我能够将它拉开以获得使用以下内容的名称.它不理想,但应该坚持下去.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
这是我的整个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;
}
Run Code Online (Sandbox Code Playgroud)