2011-01-28 25 views
5

Jasper ile raporu yüklemek için kaynakları kullanıyorum. Yani, ana rapor yüklenmeye, şöyle bir şey kullanın: report1.jrxml bir alt rapor varsa,Jasper ile alt rapor kaynakları nasıl yüklenir?

InputStream is = getClass().getResourceAsStream("/resources/report1.jrxml"); 
design = JRXmlLoader.load(is); 

Fakat, nasıl /resources/sub.jrxml olduğunu söylemek?

jasperDesign = JRXmlLoader.load(rootpath + "/WEB-INF/templates/Report.jrxml"); 
jasperDesignSR = JRXmlLoader.load(rootpath + "/WEB-INF/templates/SubReport.jrxml"); 


JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign); 
JasperReport jasperReportSR = JasperCompileManager.compileReport(jasperDesignSR); 

parameters.put("SubReportParam", jasperReportSR); 
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource); 

"SubReportParam" senin Raporunda içinde SubreportExpression olarak tip "JasperReport" bir parametre olacaktır:

cevap

15

Ben öyle yaptım. .jrxml olarak

:

<parameter name="SubReportParam" class="net.sf.jasperreports.engine.JasperReport" isForPrompting="false"/> 

Sen Raporlarının sizin Tasarım İReport kullanırsanız bilmiyorum. Alt raporunuza sağ tıklayarak SubreportExpression'u bulun. parametreleri, "fillReport" alanına ilettiğim bir haritadır.

İyi şanslar.

3

lkdg'nin cevabı ile oldukça mutlu değildim çünkü tasarımdan doğru dosyayı yükleme endişesini ayırmak istedim, çünkü JRXML'in tasarım zamanında raporların yüklendiği yerden düzenlemeye zorlanmamalıyım. Dosyalar.

Maalesef Jasper Kütüphanesi'nin kodu, özel bir alt yüklenicinin enjeksiyonu için doğru noktayı bulmayı zorlaştıran statik referanslarla doludur ve ayrıca belgelerin bir kısmı berbattır (ör. RepositoryService arayüzü tamamen bir sözleşmeden yoksundur dokümantasyon yüzden) kodu çağırarak okuyarak sözleşme tahmin gerekiyordu, ancak mümkündür:

private static void fillReport() throws IOException, JRException { 
    // The master report can be loaded just like that, because the 
    // subreports will not be loaded at this point, but later when 
    // report is filled. 
    final JasperReport report = loadReport("masterReport.jasper"); 

    // The SimpleJasperReportsContext allows us to easily specify some 
    // own extensions that can be injected into the fill manager. This 
    // class will also delegate to the DefaultJasperReportsContext and 
    // combine results. Thus all the default extensions will still be available 
    SimpleJasperReportsContext jasperReportsContext = new SimpleJasperReportsContext(); 
    jasperReportsContext.setExtensions(
     RepositoryService.class, singletonList(new SubReportFindingRepository()) 
    ); 

    final byte[] pdf = JasperExportManager.exportReportToPdf(
     JasperFillManager 
      .getInstance(jasperReportsContext) 
      // carefully select the correct `fill` method here and don't 
      // accidentally select one of the static ones!: 
      .fill(report, YOUR_PARAMS, YOUR_CONNECTION) 
    ); 
} 

private static JasperReport loadReport(final String fileName) throws IOException, JRException { 
    try(InputStream in = loadReportAsStream(fileName)) { 
     return (JasperReport) JRLoader.loadObject(in); 
    } 
} 

private static InputStream loadReportAsStream(final String fileName) { 
    final String resourceName = "/package/path/to/reports/" + fileName; 
    final InputStream report = CurrentClass.class.getResourceAsStream(resourceName); 
    if (report == null) { 
     throw new RuntimeException("Report not found: " + resourceName); 
    } 
    return report; 
} 

private static class SubReportFindingRepository implements RepositoryService { 


    @Override 
    public Resource getResource(final String uri) { 
     return null; // Means "not found". The next RepositoryService will be tried 
    } 

    @Override 
    public void saveResource(final String uri, final Resource resource) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public <K extends Resource> K getResource(final String uri, final Class<K> resourceType) { 
     if (!isKnownSubReport(uri)) { 
      return null; // Means "not found". The next RepositoryService will be tried 
     } 

     final ReportResource reportResource = new ReportResource(); 
     try { 
      reportResource.setReport(loadReport(uri)); 
     } catch (IOException | JRException e) { 
      throw new Error(e); 
     } 
     return resourceType.cast(reportResource); 
    } 

    private static boolean isKnownSubReport(final String uri) { 
     return "subReport1.jasper".equals(uri) || "subReport2.jasper".equals(uri); 
    } 
} 

ayrıca bir global extension yazabilir yerel enjeksiyon alternatif olarak. Anladığım kadarıyla (denemedim) bu, raporları yüklemek için özel bir depo içerebilecek şekilde yüklenilmesi gereken sınıf adlarıyla bir jasperreports_extension.properties dosyasının oluşturulmasını gerektirir. Ancak bu durumda, farklı kullanım durumlarında ihtiyaç duyulan çatışan konfigürasyonlarla çalışma kabiliyetinizi tamamen kaybedersiniz.

İlgili konular