如何在 JasperReports 中构建包含大量摘要的报告
How can I build a report with large summary in JasperReports
我正在尝试通过为桌面应用程序设计的报告来满足一些要求。我会尽可能清楚地解释我自己。情况如下:
我有一份报告,在 <detail>
范围内有一个简单的 table,然后是很大一部分静态文本和 2 或 3 个表达式,它们应该对应于 <summary>
乐队。一开始,我试图将所有这些信息放在 <summary>
中,但后来我发现了 JasperReports bands 的 656px 高度限制。
我解决该问题的第二次尝试是将该静态摘要信息放入子报表中。这样我就可以使用 <title>
和 <summary>
带将字段放在两个带中,而不必担心带高度限制。该解决方案的问题是我无法在子报表部分(有 2 或 3 页)中显示页码(来自第一个报表)。我在 summary 中找到了 页脚和页眉的选项(Jaspersoft Studio 中的一个复选框,它是 <jasperReport>
元素中的 isSummaryWithPageHeaderAndFooter="true"
属性 )但是然后我的报告在预览时给我一个编译错误;不知道是不是Jaspersoft Studio的bug:我试了2个最新的版本,都是一样的错误。
最后,我尝试添加第二个 <detail>
带不同的查询,其中 returns 只有一个值。现在的问题是我无法将第二个详细信息带 “置于第一个” 下方:在预览中,我交替看到每个带的一行,而不是我需要的。查了很多才知道这是不可能的
导致问题的摘要要求
摘要有以下要求:
- 有几个静态文本字段和一些其他带有计算字段和参数的表达式(格式化日期和类似的东西)。
- 这些页面必须分页(页脚中 [总] 页的 [当前] 页)。
- 主报表和摘要的数据源和查询相同。
第一个要求是摘要带区的高度需要大于 656 像素,这是该带区允许的最大值。所以我尝试了上面简要描述的解决方案。我现在将描述子报表方法的问题。
子报表 isSummaryWithPageHeaderAndFooter="true"
当我尝试使用这种方法从 Jaspersoft Studio 预览报告时,首先我得到以下状态(在 IDE 请求参数之前):
当我输入参数时,我得到以下状态:
之后,时间和页面不断增长,直到程序崩溃。相同的行为发生在不同的安装中:我在 Windows 7 和 Mac OS 中尝试了版本 6.3.1 和 6.4.0。但是,使用编译报告选项从 IDE 编译报告是成功的(我的意思是它生成 .jasper
文件)。
但是当我将报告导出为 PDF(或使用 JasperViewer
显示)时,它不会在摘要带中使用页脚呈现。
注意: 从一个简单的 Java 应用程序编译报告不会给我任何错误。
欢迎任何帮助。提前致谢。
您可以添加一个不会产生任何中断的虚拟组,并将第二个详细信息的内容放在组页脚区域中。
经过大量研究,尝试了许多选项并提出了另一个问题,我终于找到了一个可以满足报告所有要求的解决方法。正如我所说,这是一种解决方法,但它对任何可能在 JasperReports 上苦苦挣扎的人都有用。
1.- 报告
首先,我制作了 2 个独立的报告,每个报告都有自己的查询和部分。每个报告都有一个名为 PAGE_COUNT_OFFSET
且类型为 Integer
的参数。在页脚中,我需要放置分页的地方我做了以下操作:
主要报告
<pageFooter>
<band height="54" splitType="Stretch">
<textField>
<reportElement x="146" y="2" width="100" height="30" uuid="1314c392-e24a-47bd-a0aa-6b19803be36a"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA["- Page " + $V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="246" y="2" width="100" height="30" uuid="230a6e2d-3e6d-4d52-9228-aab519122537"/>
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[" of " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET}) + " -"]]></textFieldExpression>
</textField>
</band>
</pageFooter>
子报表
<pageFooter>
<band height="50">
<property name="com.jaspersoft.studio.unit.height" value="pixel"/>
<textField>
<reportElement x="146" y="2" width="100" height="30" uuid="b6a836b2-41f5-4a61-af64-50720544cef2"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA["- Page " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET})]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="246" y="2" width="100" height="30" uuid="be5469d3-10ed-4deb-964d-c1f9c9b7337a"/>
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[" of " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET}) + " -"]]></textFieldExpression>
</textField>
</band>
</pageFooter>
注:还要感谢Petter Friberg for ,对我帮助很大
2.- 报告填写
要使此过程成功,不需要在每次执行时都编译报告,您只需要在编译的 .jasper
文件中填充数据即可。我使用 Java 例程以编程方式执行此操作。我将使用 main
方法进行展示和示例,在实践中,您会将此逻辑写入方法主体或类似的东西中。
注意: 我假设 .jasper
文件打包在 JAR 文件的根目录中。
public static void main(String[] args) {
try {
// Build parameters map with fake offset
Map<String, Object> subreportParams = new HashMap<>();
// PARAM_PAGE_COUNT_OFFSET is a convenient String constant with the parameter name for the report
subreportParams.put(PARAM_PAGE_COUNT_OFFSET, 10);
Map<String, Object> mainParams = new HashMap<>(subreportParams);
mainParams.put(...); // Some other parameters
// Fill the report the first time and get the real page count for every report
ClassLoader classLoader = getClass().getClassLoader();
// Again, MAIN_REPORT_FILE and SUBREPORT_FILE are String constants containing jasper files names
// JdbcManager.getConnection() is a utility method which gets a connection with predefined parameters
JasperPrint main = JasperFillManager.fillReport(classLoader.getResourceAsStream(MAIN_REPORT_FILE), mainParams, JdbcManager.getConnection());
JasperPrint subreport = JasperFillManager.fillReport(classLoader.getResourceAsStream(SUBREPORT_FILE), subreportParams, JdbcManager.getConnection());
// Get the page count for every report and reinsert it in the parameters map
int mainPageCount = main.getPages().size();
int subreportPageCount = subreport.getPages().size();
// The offset for the given report should be the count from the other
mainParams.put(PARAM_PAGE_COUNT_OFFSET, subreportPageCount);
subreportParams.put(PARAM_PAGE_COUNT_OFFSET, mainPageCount);
// Fill with the final parameters and generates a JpList object
main = JasperFillManager.fillReport(classLoader.getResourceAsStream(MAIN_REPORT_FILE), mainParams, JdbcManager.getConnection());
subreport = JasperFillManager.fillReport(classLoader.getResourceAsStream(SUBREPORT_FILE), subreportParams, JdbcManager.getConnection());
List<JasperPrint> finalReport = new ArrayList<>();
finalReport.add(main);
finalReport.add(subreport);
// Export the report and save it to a given path
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(SimpleExporterInput.getInstance(finalReport));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(
new FileOutputStream("path/to/report.pdf")));
exporter.exportReport();
} catch (JRException ex) {
LOGGER.log(Level.SEVERE, "Error generating report", ex);
} catch (FileNotFoundException ex) {
LOGGER.log(Level.SEVERE, "Error saving file", ex);
}
}
通过这种方式,我获得了单个 PDF 格式的报告并正确分页。希望对任何人都有帮助。最好的问候。
我正在尝试通过为桌面应用程序设计的报告来满足一些要求。我会尽可能清楚地解释我自己。情况如下:
我有一份报告,在 <detail>
范围内有一个简单的 table,然后是很大一部分静态文本和 2 或 3 个表达式,它们应该对应于 <summary>
乐队。一开始,我试图将所有这些信息放在 <summary>
中,但后来我发现了 JasperReports bands 的 656px 高度限制。
我解决该问题的第二次尝试是将该静态摘要信息放入子报表中。这样我就可以使用 <title>
和 <summary>
带将字段放在两个带中,而不必担心带高度限制。该解决方案的问题是我无法在子报表部分(有 2 或 3 页)中显示页码(来自第一个报表)。我在 summary 中找到了 页脚和页眉的选项(Jaspersoft Studio 中的一个复选框,它是 <jasperReport>
元素中的 isSummaryWithPageHeaderAndFooter="true"
属性 )但是然后我的报告在预览时给我一个编译错误;不知道是不是Jaspersoft Studio的bug:我试了2个最新的版本,都是一样的错误。
最后,我尝试添加第二个 <detail>
带不同的查询,其中 returns 只有一个值。现在的问题是我无法将第二个详细信息带 “置于第一个” 下方:在预览中,我交替看到每个带的一行,而不是我需要的。查了很多才知道这是不可能的
导致问题的摘要要求
摘要有以下要求:
- 有几个静态文本字段和一些其他带有计算字段和参数的表达式(格式化日期和类似的东西)。
- 这些页面必须分页(页脚中 [总] 页的 [当前] 页)。
- 主报表和摘要的数据源和查询相同。
第一个要求是摘要带区的高度需要大于 656 像素,这是该带区允许的最大值。所以我尝试了上面简要描述的解决方案。我现在将描述子报表方法的问题。
子报表 isSummaryWithPageHeaderAndFooter="true"
当我尝试使用这种方法从 Jaspersoft Studio 预览报告时,首先我得到以下状态(在 IDE 请求参数之前):
当我输入参数时,我得到以下状态:
之后,时间和页面不断增长,直到程序崩溃。相同的行为发生在不同的安装中:我在 Windows 7 和 Mac OS 中尝试了版本 6.3.1 和 6.4.0。但是,使用编译报告选项从 IDE 编译报告是成功的(我的意思是它生成 .jasper
文件)。
但是当我将报告导出为 PDF(或使用 JasperViewer
显示)时,它不会在摘要带中使用页脚呈现。
注意: 从一个简单的 Java 应用程序编译报告不会给我任何错误。
欢迎任何帮助。提前致谢。
您可以添加一个不会产生任何中断的虚拟组,并将第二个详细信息的内容放在组页脚区域中。
经过大量研究,尝试了许多选项并提出了另一个问题,我终于找到了一个可以满足报告所有要求的解决方法。正如我所说,这是一种解决方法,但它对任何可能在 JasperReports 上苦苦挣扎的人都有用。
1.- 报告
首先,我制作了 2 个独立的报告,每个报告都有自己的查询和部分。每个报告都有一个名为 PAGE_COUNT_OFFSET
且类型为 Integer
的参数。在页脚中,我需要放置分页的地方我做了以下操作:
主要报告
<pageFooter>
<band height="54" splitType="Stretch">
<textField>
<reportElement x="146" y="2" width="100" height="30" uuid="1314c392-e24a-47bd-a0aa-6b19803be36a"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA["- Page " + $V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="246" y="2" width="100" height="30" uuid="230a6e2d-3e6d-4d52-9228-aab519122537"/>
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[" of " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET}) + " -"]]></textFieldExpression>
</textField>
</band>
</pageFooter>
子报表
<pageFooter>
<band height="50">
<property name="com.jaspersoft.studio.unit.height" value="pixel"/>
<textField>
<reportElement x="146" y="2" width="100" height="30" uuid="b6a836b2-41f5-4a61-af64-50720544cef2"/>
<textElement textAlignment="Right"/>
<textFieldExpression><![CDATA["- Page " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET})]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="246" y="2" width="100" height="30" uuid="be5469d3-10ed-4deb-964d-c1f9c9b7337a"/>
<textElement textAlignment="Left"/>
<textFieldExpression><![CDATA[" of " + ($V{PAGE_NUMBER} + $P{PAGE_COUNT_OFFSET}) + " -"]]></textFieldExpression>
</textField>
</band>
</pageFooter>
注:还要感谢Petter Friberg for
2.- 报告填写
要使此过程成功,不需要在每次执行时都编译报告,您只需要在编译的 .jasper
文件中填充数据即可。我使用 Java 例程以编程方式执行此操作。我将使用 main
方法进行展示和示例,在实践中,您会将此逻辑写入方法主体或类似的东西中。
注意: 我假设 .jasper
文件打包在 JAR 文件的根目录中。
public static void main(String[] args) {
try {
// Build parameters map with fake offset
Map<String, Object> subreportParams = new HashMap<>();
// PARAM_PAGE_COUNT_OFFSET is a convenient String constant with the parameter name for the report
subreportParams.put(PARAM_PAGE_COUNT_OFFSET, 10);
Map<String, Object> mainParams = new HashMap<>(subreportParams);
mainParams.put(...); // Some other parameters
// Fill the report the first time and get the real page count for every report
ClassLoader classLoader = getClass().getClassLoader();
// Again, MAIN_REPORT_FILE and SUBREPORT_FILE are String constants containing jasper files names
// JdbcManager.getConnection() is a utility method which gets a connection with predefined parameters
JasperPrint main = JasperFillManager.fillReport(classLoader.getResourceAsStream(MAIN_REPORT_FILE), mainParams, JdbcManager.getConnection());
JasperPrint subreport = JasperFillManager.fillReport(classLoader.getResourceAsStream(SUBREPORT_FILE), subreportParams, JdbcManager.getConnection());
// Get the page count for every report and reinsert it in the parameters map
int mainPageCount = main.getPages().size();
int subreportPageCount = subreport.getPages().size();
// The offset for the given report should be the count from the other
mainParams.put(PARAM_PAGE_COUNT_OFFSET, subreportPageCount);
subreportParams.put(PARAM_PAGE_COUNT_OFFSET, mainPageCount);
// Fill with the final parameters and generates a JpList object
main = JasperFillManager.fillReport(classLoader.getResourceAsStream(MAIN_REPORT_FILE), mainParams, JdbcManager.getConnection());
subreport = JasperFillManager.fillReport(classLoader.getResourceAsStream(SUBREPORT_FILE), subreportParams, JdbcManager.getConnection());
List<JasperPrint> finalReport = new ArrayList<>();
finalReport.add(main);
finalReport.add(subreport);
// Export the report and save it to a given path
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(SimpleExporterInput.getInstance(finalReport));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(
new FileOutputStream("path/to/report.pdf")));
exporter.exportReport();
} catch (JRException ex) {
LOGGER.log(Level.SEVERE, "Error generating report", ex);
} catch (FileNotFoundException ex) {
LOGGER.log(Level.SEVERE, "Error saving file", ex);
}
}
通过这种方式,我获得了单个 PDF 格式的报告并正确分页。希望对任何人都有帮助。最好的问候。