好的,所以需要一些技巧才行,但我能够想出一个解决方案...
subreport.getExpression().getText() 返回主报表中子报表小部件的表达式字段,是一个类似于以下内容的字符串
$P{SUBREPORT_DIR} + "/report_sub1.jasper"
所以我使用以下方法将其拆开,以获取名称。虽然不理想,但应该能够解决问题。
JRElementsVisitor.visitReport(jasperReport, new JRVisitor(){
@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;
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");
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();
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;
}