2012-04-04 17 views
8

Mam autonomiczną aplikację, a jednym z jej obowiązków jest pobranie ścieżki pliku * .jrxml i skompilowanie go.Raporty Jaspera: jak kompilować podraporty

Mogę to zrobić bez problemu, dopóki nie pojawi się raport z podraportem, w którym kompilacja wzorca nie kompiluje żadnego z jej elementów podrzędnych, co spowoduje, że plik podrzędny * .jasper nie zostanie odnaleziony w dalszej części ścieżki.

Czy istnieje jakiś sposób, aby

1) Ustaw JasperCompileManager automatycznie odebrać podraporty?

2) Uzyskaj listę ścieżek do podraportów zawartych w obiekcie JasperDesign lub JasperReport?

Nie mam bezpośredniego dostępu do plików jrxml, więc modyfikowanie raportów zgodnie z metodą kompilacji nie jest opcją, ani nie stosuje żadnego standardowego schematu nazewnictwa, aby wywnioskować, które podraporty należą do których raportów.

Jest podobny problem tutaj:

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

gdzie JRVisitor jest używany do produkcji listę obiektów JRSubreport, jednak brak jest wyjaśnienie, w jaki sposób to wykorzystać, aby uzyskać ścieżkę do podraportu w celu skompilowania go i rekurencyjnego wyszukiwania podraportów podraportów, i nie mogę tego zrozumieć.

+0

Chciałbym usłyszeć odpowiedź. Skończyć link do pliku * .jasper subraport bezpośrednio, a następnie skompilować go w locie. :( –

+0

Podobny problem rozwiązano bez zapisywania plików na dysku: http://stackoverflow.com/questions/9785451/generate-jasper-report-with-subreport-from-java –

Odpowiedz

8

Ok, więc to wymaga trochę hackery, ale udało mi się coś wymyślimy ...

subreport.getExpression(). GetText() zwraca pole ekspresji rzeczy widget Podraport w raport master, a jest ciągiem znaków, który wygląda mniej więcej tak

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

Więc byłem w stanie wyciągnąć go od siebie, aby uzyskać nazwę stosując następujący. Nie jest idealny, ale powinien wytrzymać.

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:

Oto cała moja metoda compileReport, demonstrując jak rekurencyjnie skompilować podraportów z podraportów itp nie jest idealne, ale wystarczająco dobre dla mojej aplikacji. Wszystkie skompilowane pliki * .jasper są zapisywane z powrotem na dysku w tej samej lokalizacji, w której zostały zebrane nieskompilowane pliki * .jrxml, ale nie byłoby to trudne do zmiany. Skompilowany główny obiekt raportu jest przekazywany z powrotem, jeśli chcesz go uruchomić lub cokolwiek innego.

Pamiętaj, że ten kod ma 9 miesięcy w czasie tej edycji, a nowsze wersje Jasper Reports mogą teraz mieć wbudowane funkcje dla tego typu rzeczy.

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

Co robi program "compileReport()"? kompilacja podraportów są przechowywane? Na dysku? – dzieciou

+0

@dzieciou Zobacz edytowane odpowiedzi powyżej – Numeron

+0

Wiem, że ma około 2 lat, ale ta odpowiedź działała jak urok dla mnie. –