当前位置: 首页 > 知识库问答 >
问题:

在java中调用Jasper子报表

穆俊杰
2023-03-14

我非常熟悉jasperstudio 6.3.0,并且能够毫无问题地从java运行其他报告。效果很好。但是,我无法运行包含子报表的报表。我在这里找到了stackoverflow的解决方案,但仍然无法使其工作。在我的解决方案中,我将报告加载到一个表中进行存储,并从数据库中提取子报告和主报告,然后编译jrxml。到那时一切都很好

网旧金山。jasperreports。发动机JREException:在以下位置找不到资源:subInvoiceSummary。贾斯珀。runReport中出错:在以下位置找不到资源:subInvoiceSummary。贾斯珀。净价。旧金山。jasperreports。回购协议。RepositoryUtil。net上的getResourceFromLocation(RepositoryUtil.java:153)。旧金山。jasperreports。回购协议。RepositoryUtil。net上的getReport(RepositoryUtil.java:112)。旧金山。jasperreports。发动机填满JR子报告。net上的loadReport(JRFillSubreport.java:398)。旧金山。jasperreports。发动机填满JR子报告。net上的evaluateReport(JRFillSubreport.java:365)。旧金山。jasperreports。发动机填满JR子报告。net上的evaluateSubreport(JRFillSubreport.java:427)。旧金山。jasperreports。发动机填满JR子报告。在net上评估(JRFillSubreport.java:341)。旧金山。jasperreports。发动机填满JRFillElementContainer。在net上计算(JRFillElementContainer.java:381)。旧金山。jasperreports。发动机填满基尔邦德。在net上评估(JRFillBand.java:500)。旧金山。jasperreports。发动机填满垂直填料。fillColumnBand(JRVerticalFiller.java:2022)在net。旧金山。jasperreports。发动机填满垂直填料。net上的fillDetail(JRVerticalFiller.java:748)。旧金山。jasperreports。发动机填满垂直填料。net上的fillReportStart(JRVerticalFiller.java:255)。旧金山。jasperreports。发动机填满垂直填料。net上的fillReport(JRVerticalFiller.java:115)。旧金山。jasperreports。发动机填满JRBaseFiller。在net上填充(JRBaseFiller.java:580)。旧金山。jasperreports。发动机填满BaseReportFiller。在net上填充(BaseReportFiller.java:396)。旧金山。jasperreports。发动机填满JRFiller。在net上填充(JRFiller.java:90)。旧金山。jasperreports。发动机我是经理。在net上填充(JasperFillManager.java:456)。旧金山。jasperreports。发动机我是经理。fillReport(JasperFillManager.java:863)

我尝试了很多排列,但都没有用。我还尝试引入jasperreports的代码来跟踪上面显示的堆栈,但是有太多了。jar依赖项和依赖项的版本我2天后无法在我的项目中编译干净(如果有人有一个简单方法的链接,请让我知道)。以下是代码片段:

Map<String, Object> rptParms = new HashMap<String, Object>();

List<daRecOnDemandSubReport> subReports = report.getOnDemandSubReport();
Iterator<daRecOnDemandSubReport> subReportList = subReports.iterator();
while (subReportList.hasNext()) {
daRecOnDemandSubReport subReport = subReportList.next();
ByteArrayInputStream x = getSubReportDataStream(dbConnROIPro, report.getODReportID());
JasperReport compiledSubReport = JasperCompileManager.compileReport(x);
String fileName = subReport.getODSubReportFileName().replace(".jrxml", ".jasper");
rptParms.put(fileName, compiledSubReport);
}

ByteArrayInputStream x = getReportDataStream(dbConnROIPro, report.getODReportID());

JasperReport cRpt = JasperCompileManager.compileReport(x);

rptParms = getReportParameters(dbConnGTrack,report.getODReportID(), rptParms, report.getOnDemandParm(), programID);

JasperPrint rpt = JasperFillManager.fillReport(cRpt,rptParms,dbConnGTrack.getDbConn());

ByteArrayOutputStream outStream = new ByteArrayOutputStream();
JRXlsxExporter XLSXexporter = new JRXlsxExporter();
   XLSXexporter.setExporterInput(new SimpleExporterInput(rpt));
   XLSXexporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outStream)); 
   XLSXexporter.exportReport();

提前感谢您的帮助

共有1个答案

苏鸿卓
2023-03-14

我也有同样的问题,从来没有找到一个简单的方法来实现这一点。Jasper开发人员自己说,他们的论坛上没有很好地实现子报告。

我用我的代码解决了这个问题。这也远不是完美的,但它是有效的。

public byte[] generateReport(ExportType exportType, String resourceName, Connection connection, Map<String, Object> parameters) throws JRException, SQLException {
    JasperReport jasperReport = loadReport(resourceName);

    LOGGER.debug("Loading subreports if any...");
    Map<String, JasperReport> subReports = loadSubReports(resourceName, jasperReport);
    parameters.putAll(subReports);

    LOGGER.debug("Filling report with JDBC and {}", parameters);
    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, connection);

    LOGGER.debug("Exporting report with {}", exportType.getClass().getSimpleName());
    byte[] pdf = exportType.export(jasperPrint);

    return pdf;
}

/**
 * Converts a system resource into a JasperReport instance.
 * If the extension is ".jasper", it tries to load a pre-compiled report.
 * If the extension is ".jrxml", it tries to compile the report.
 */
private JasperReport loadReport(String resourceName) throws JRException {
    JasperReport jasperReport = null;
    InputStream inputStream = this.getClass().getResourceAsStream(resourceName);

    if (inputStream != null) {
        if (resourceName.toLowerCase().endsWith(JASPER)) {
            LOGGER.debug("Loading pre-compiled report: {}", resourceName);
            jasperReport = (JasperReport) JRLoader.loadObject(inputStream);
        } else {
            LOGGER.debug("Compiling XML report: {}", resourceName);
            jasperReport = JasperCompileManager.compileReport(inputStream);
        }
    } else {
        LOGGER.warn("Unable to open resource: {}", resourceName);
    }
    return jasperReport;
}

/**
 * Parses a Report for SubReport parameters.
 * A Parameter has to be a <code>java.lang.Object</code> or a <code>net.sf.jasperreports.engine.JasperReport</code> to be considered a SubReport Input
 * An Object parameter has the advantage to allow Jasper Report's IDE to accept a Filename String resource.
 * If the parameter is an Object, the Filename declared as <b>default value</b> is used to load the SubReport.
 * If the parameter is a JasperReport, the parameter's name is used instead.
 * 
 * The default value, or the parameter's name, have to use a ".jasper" or ".jrxml" extension.
 * The SubReport resource's path has to be located relatively to the parent Report.
 */
private Map<String, JasperReport> loadSubReports(String masterResource, JasperReport jasperReport) throws JRException {
    Map<String, JasperReport> subReportExpressions = new HashMap<>();
    String masterPath = FilenameUtils.getFullPath(masterResource);

    for (JRParameter jrParameter : jasperReport.getParameters()) {
        String subReportName = getSubReportName(jrParameter);
        if (subReportName != null) {
            String name = jrParameter.getName();
            JasperReport subReport = loadReport(masterPath + subReportName);
            subReportExpressions.put(name, subReport);
        }
    }
    return subReportExpressions;
}


/**
 * Analyses the parameter to find a SubReport resource name respecting the defined rules
 * 
 * @return The filename of the resource, or null
 */
private String getSubReportName(JRParameter jrParameter) {
    String ret = null;
    Class<?> valueClass = jrParameter.getValueClass();
    boolean isObject = (valueClass == Object.class);
    boolean isJasperReport = (valueClass == JasperReport.class);

    // If the parameter is an Object,
    // we take the SubReport name from the default value (a String)
    if (isObject) {
        String defaultValue = getDefaultValue(jrParameter);
        if (defaultValue != null && checkExtension(defaultValue)) {
            ret = defaultValue;
        }
    }

    // If the parameter is a JasperReport, or an Object without a correct defaultValue,
    // we take the SubReport name from the parameter's name
    if (isJasperReport || (ret == null && isObject)) {
        String name = jrParameter.getName();
        if (checkExtension(name)) {
            ret = name;
        }
    }
    return ret;
}


private boolean checkExtension(String defaultValue) {
    defaultValue = defaultValue.toLowerCase();
    return defaultValue.endsWith(JRXML) || defaultValue.endsWith(JASPER);
}

private String getDefaultValue(JRParameter jrParameter) {
    String ret = null;
    JRExpression defaultValueExpression = jrParameter.getDefaultValueExpression();
    if (defaultValueExpression != null) {
        ret = defaultValueExpression.getText();
        if (ret != null && ret.length() > 2 && ret.startsWith(QUOTE) && ret.endsWith(QUOTE)) {
            // Removing quotes from the String
            ret = ret.substring(1, ret.length() - 1);
        }
    }
    return ret;
}

希望这有帮助。如果有人有更好的解决办法,我会喜欢你的问题。

 类似资料:
  • 我正在尝试使用java swing创建一个报表,它能够打印我在SQL数据库中的数据,我在搜索了我的问题后发现了这个问题,我遵循了一步一步的教程,一切都很顺利,没有错误发生,一开始看起来很好,但在我把这些代码(将生成我想要的报表): 在我运行程序并单击buttong报告后,出现了一个错误并打印如下: 谁能告诉我怎么修这个吗?我错过什么了吗?

  • 当简单报表不适用于子报表时,此操作有效...

  • 我正在Jasper报表中制作一个简单的报表,数据源java bean。我在做一个表格的报告。在jaspersoft studio中,表是可见的,但当我生成报告时,表是不可见的,其余的条目是很好的和可见的。我已添加“详细信息表”部分。 xml代码: 添加值的Java代码

  • 我的应用程序中有几个类似的报告,因此我创建了一个基本结构,在标题中有一个子报告,在页脚中有另一个子报告。 我不知道为什么我找不到解决这个问题的方法,如果有人能帮我...谢谢!

  • 我对从web服务调用jasper报告有问题。 我使用这个URL http://host:port/jasperserver[-pro]/rest_v2/reportexecutions获取请求id,输出类似于下面的XML。 现在我正尝试通过以下url运行jasper报表 http://localhost:8080/jasperserver/rest_v2/reportexecutions/7818

  • 我正在使用Jaspersoft studio创建报告。我在我的Jasper主报告中有一个子报告。问题是,我无法做到这一点,因为如果我将子报告添加到主报告的< code>Detail band中,子报告会生成多次,有时是逐行生成,有时是整个子报告在若干页中重复。出于同样的原因,我不能把它放在< code > summer Band 中。 我无法将其放入或其他页脚中,因为它显示以下错误 由于以下错误,