2012-04-04 24 views
8

Ho un'applicazione autonoma e uno dei suoi compiti è quello di prendere il percorso di un file * .jrxml e compilarlo.Rapporti Jasper: Come compilare sottoreport

Posso farlo senza problemi finché non viene visualizzato un report con un sottoreport, in cui la compilazione del master non compila nessuno dei suoi figli, risultando in un file di sottoreport * .jasper non trovato più avanti lungo la traccia.

Esiste un modo per

1) Impostare il JasperCompileManager per raccogliere automaticamente subreports?

2) Ottenere un elenco di percorsi per i sottoreport contenuti in un oggetto JasperDesign o JasperReport?

Non ho accesso diretto ai file jrxml, quindi la modifica dei report per soddisfare il metodo di compilazione non è un'opzione, né si applica uno schema di denominazione standard per dedurre quali sottoreport appartengono a quali report.

C'è un problema simile qui:

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

dove un JRVisitor viene utilizzato per la produzione di un elenco di oggetti JRSubreport, tuttavia non v'è alcuna spiegazione di come utilizzare questo per ottenere un percorso per il sottoreport per compilarlo e cercare in modo ricorsivo i sottoreport dei sottoreport, e non riesco a capirlo.

+0

Mi piacerebbe sentire anche la risposta. Ho finito per collegarmi direttamente al file * .jasper del sottotitolo piuttosto che a compilarlo al volo. :( –

+0

Problema simile risolto senza salvare i file su disco: http://stackoverflow.com/questions/9785451/generate-jasper-report-with-subreport-from-java –

risposta

8

Ok, quindi ha richiesto un po 'di aggiustamenti, ma sono stato in grado di capire qualcosa ...

Il subreport.getExpression(). GetText() restituisce il campo espressione del widget sottoreport cosa al rapporto maestro, ed è una stringa che assomigli a questo

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

Così mi è stato in grado di tirare a parte per ottenere il nome utilizzando la seguente. Non è l'ideale, ma dovrebbe reggere.

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:

Ecco tutto il mio metodo compileReport, dimostrando come compilare in modo ricorsivo subreports di subreports ecc non perfetto, ma abbastanza buono per la mia app. Tutti i file * .jasper compilati vengono salvati su disco nella stessa posizione in cui sono stati raccolti i file * .jrxml non compilati, ma questo non sarebbe difficile da modificare. L'oggetto report principale compilato viene restituito in caso si voglia eseguirlo o altro.

Ricordare che questo codice ha 9 mesi al momento di questa modifica e le versioni più recenti di Jasper Reports possono ora avere una funzione inbuild per questo tipo di operazioni.

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; 
} 
+0

Cosa fa 'compileReport()' do? Dove vengono la compilazione dei sottoreport è memorizzata? Sul disco? – dzieciou

+0

@dzieciou Vedere la risposta modificata sopra. – Numeron

+0

So che ha circa 2 anni, ma questa risposta ha funzionato come un fascino per me. –

Problemi correlati