Java 在导出中合并多个jasper报表时,如何重新计算页码?
在聊天室收到关于如何处理jasper报告中的页码的问题和答案后,我决定通过此问答 使用Java 在导出中合并多个jasper报表时,如何重新计算页码?,java,jasper-reports,Java,Jasper Reports,在聊天室收到关于如何处理jasper报告中的页码的问题和答案后,我决定通过此问答 使用 JasperPrint jasperPrint1 = JasperFillManager.fillReport(report1, paramMap); JasperPrint jasperPrint2 = JasperFillManager.fillReport(report2, paramMap); List<JasperPrint> jasperPrintList = Arrays.asLis
JasperPrint jasperPrint1 = JasperFillManager.fillReport(report1, paramMap);
JasperPrint jasperPrint2 = JasperFillManager.fillReport(report2, paramMap);
List<JasperPrint> jasperPrintList = Arrays.asList(jasperPrint1, jasperPrint2);
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(SimpleExporterInput.getInstance(jasperPrintList));
JasperPrint jasperPrint1=JasperFillManager.fillReport(report1,paramMap);
JasperPrint jasperPrint2=JasperFillManager.fillReport(report2,paramMap);
List jasperPrintList=Arrays.asList(jasperPrint1,jasperPrint2);
JRPdfExporter exporter=新的JRPdfExporter();
setExporterInput(SimpleExporterInput.getInstance(jasperPrintList));
页码和总页码
对于我包含在列表中的每个报表,都会重新启动,是否有方法可以重新计算这些报表
考虑到我的最终合并报告,我希望在每一页上显示当前页面(以及正确的总页数)
jasper报告的方式不是在java中组合报告,而是使用
主报告,并将不同的报告作为子报告包含在此主报告中
报告,将页码移动到主报告
但是,如果我们喜欢像在问题中那样在java中组合,我们也可以使用java来编辑和更正页码
这个想法是在报告中设置“标记”,然后对JasperPrint
进行后期处理,用实际页码替换标记
例子
jrxml(使用freemaker风格毫无羞耻)
java
定义我的标记
private静态最终字符串CURRENT\u PAGE\u NUMBER=“${CURRENT\u PAGE\u NUMBER}”;
私有静态最终字符串TOTAL_PAGE_NUMBER=“${TOTAL_PAGE_NUMBER}”;
在我的报告的fillReport
之后,用真数字替换我的所有标记
//First loop on all reports to get totale page number
int totPageNumber=0;
for (JasperPrint jp : jasperPrintList) {
totPageNumber += jp.getPages().size();
}
//Second loop all reports to replace our markers with current and total number
int currentPage = 1;
for (JasperPrint jp : jasperPrintList) {
List<JRPrintPage> pages = jp.getPages();
//Loop all pages of report
for (JRPrintPage jpp : pages) {
List<JRPrintElement> elements = jpp.getElements();
//Loop all elements on page
for (JRPrintElement jpe : elements) {
//Check if text element
if (jpe instanceof JRPrintText){
JRPrintText jpt = (JRPrintText) jpe;
//Check if current page marker
if (CURRENT_PAGE_NUMBER.equals(jpt.getValue())){
jpt.setText("Page " + currentPage + " of"); //Replace marker
continue;
}
//Check if totale page marker
if (TOTAL_PAGE_NUMBER.equals(jpt.getValue())){
jpt.setText(" " + totPageNumber); //Replace marker
}
}
}
currentPage++;
}
}
这是正确的,但如果有JRPrintFrame,并且如果您的注释在代码中,则无法找到它。下面是一个为我工作的:(你应该找出总页数在哪个容器元素中
private void correctPageNumbers(List<JasperPrint> jasperPrintList) {
// First loop on all reports to get totale page number
int totPageNumber = 0;
for (JasperPrint jp : jasperPrintList) {
totPageNumber += jp.getPages().size();
}
// Second loop all reports to replace our markers with current and total
// number
int currentPage = 1;
for (JasperPrint jp : jasperPrintList) {
List<JRPrintPage> pages = jp.getPages();
// Loop all pages of report
for (JRPrintPage jpp : pages) {
List<JRPrintElement> elements = jpp.getElements();
// Loop all elements on page
for (JRPrintElement jpe : elements) {
if (jpe instanceof JRSubreport) {
JRSubreport jrr = (JRSubreport) jpe;
jrr.getBackcolor();
}
// Check if text element
if (jpe instanceof JRPrintText) {
JRPrintText jpt = (JRPrintText) jpe;
System.out.println("jpt.value: " + jpt.getValue() + " | " + "jpt.text" + jpt.getText());
// Check if totale page marker
if (TOTAL_PAGE_NUMBER.equals(jpt.getValue())) {
jpt.setText(" " + totPageNumber); // Replace marker
}
} else if (jpe instanceof JRTemplatePrintFrame) {
List<JRPrintElement> frameElements = ((JRTemplatePrintFrame) jpe).getElements();
for (JRPrintElement jpef : frameElements) {
if (jpef instanceof JRPrintText) {
JRPrintText jpt = (JRPrintText) jpef;
System.out.println("jpt.value: " + jpt.getValue() + " | " + "jpt.text"
+ jpt.getText());
// Check if totale page marker
if (TOTAL_PAGE_NUMBER.equals(jpt.getValue())) {
jpt.setText(" " + totPageNumber); // Replace
// marker
}
}
}
}
}
currentPage++;
}
}
private void correctPageNumber(列表jasperPrintList){
//所有报告上的第一个循环,以获取总页码
int-totPageNumber=0;
用于(JasperPrint jp:jasperPrintList){
totPageNumber+=jp.getPages().size();
}
//第二次循环所有报告,用当前和总计替换标记
//数
int currentPage=1;
用于(JasperPrint jp:jasperPrintList){
List pages=jp.getPages();
//循环报告的所有页面
用于(JRPrintPage jpp:pages){
List elements=jpp.getElements();
//循环页面上的所有元素
用于(JRPrintElement jpe:elements){
if(JRSubreport的jpe实例){
JRSubreport jrr=(JRSubreport)jpe;
jrr.getBackcolor();
}
//检查是否存在文本元素
if(JRPrintText的jpe实例){
JRPrintText jpt=(JRPrintText)jpe;
System.out.println(“jpt.value:+jpt.getValue()+”|“+”jpt.text“+jpt.getText());
//检查全页标记是否正确
if(总页数等于(jpt.getValue()){
jpt.setText(“+totPageNumber);//替换标记
}
}else if(JRTemplatePrintFrame的jpe实例){
List frameElements=((JRTemplatePrintFrame)jpe.getElements();
用于(JRPrintElement jpef:frameElements){
if(JRPrintText的jpef实例){
JRPrintText jpt=(JRPrintText)jpef;
System.out.println(“jpt.value:+jpt.getValue()+”|“+”jpt.text”
+getText());
//检查全页标记是否正确
if(总页数等于(jpt.getValue()){
jpt.setText(“+totPageNumber);//替换
//标记
}
}
}
}
}
currentPage++;
}
}
}还有一个简单的解决方案,它不适用于像JasperPrint和JasperPages这样的jasper类。 方法是获取以前打印的页数,并将其添加到下一次打印的页码变量中 假设我们有三张碧玉印花。 jasperPrint1、jasperPrint2、jasperPrint3,因为jasperPrint1具有动态内容和可变页数,所以很难知道下一次打印的页码。解决方案是- 将第一次打印导出到临时pdf文件-
JasperExportManager.exportReportToPdfFile(jasperPrint1,
tempPdfFile.getAbsolutePath());
初始化一个变量,该变量使用0跟踪所有以前打印的页面
pafeSofar = 0
编写一个方法以返回pdf文件中的页数:
private int numberOfPages(String filePath) throws IOException {
PdfReader pdfReader = new PdfReader(filePath);
return pdfReader.getNumberOfPages();
}
这里PdfReader是iText中的一个类。您可以添加一个maven依赖项或手动下载一个.jar并将其添加到类路径中
itext pdf阅读器的Maven依赖项如下:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.0</version>
</dependency>
创建一个参数以将此变量传递到,并将该参数添加到其他报表的页码中
parameterMap.put("previousPageNumber", pagesSofar);`
在.jrxml文件中:
<textField>
<reportElement x="232" y="1" width="100" height="20"/>
<textFieldExpression><![CDATA[$V{PAGE_NUMBER}+$P{previousPageNumber}]]>
</textFieldExpression>
</textField>`
我受到@Adityaz7 answer的启发,我认为他的方法是最好的。但我这样做不需要向项目中添加库和创建临时PDF文件 首先,修改模板并添加一个参数来保存以前的页数:
<parameter name="PREVIOUS_PAGE_NUMBER" class="java.lang.Integer"/>
我写这篇内联文章是为了尊重问题中使用的结构OP,但如果要打印的报告超过2份,当然最好是在一个循环中完成。是的,这并不是因为依赖性(因为jasper report已经因为许可证问题将if转换为另一个itext版本),但由于您只想导出一次到pdf(因此所有的JasperPrint都是如此),JasperReport已经提供了itext(即使另一个版本没有商业问题),唯一的问题是您要在t中多次导出到pdf
<textField>
<reportElement x="232" y="1" width="100" height="20"/>
<textFieldExpression><![CDATA[$V{PAGE_NUMBER}+$P{previousPageNumber}]]>
</textFieldExpression>
</textField>`
JasperPrint jasperPrint2 = JasperFillManager.fillReport(jasperReport3, parameterMap, new JREmptyDataSource());
<parameter name="PREVIOUS_PAGE_NUMBER" class="java.lang.Integer"/>
<textFieldExpression><![CDATA[String.valueOf($V{PAGE_NUMBER} + $P{PREVIOUS_PAGE_NUMBER})]></textFieldExpression>
int prevPageNumber = 0;
HashMap<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("PREVIOUS_PAGE_NUMBER", prevPageNumber);
// fill the first report with prevPageNumber = 0
JasperPrint jasperPrint1 = JasperFillManager.fillReport(report1, paramMap);
if(jasperPrint1 != null && jasperPrint1.getPages() != null)
{
// add previous report page number
prevPageNumber += jasperPrint1.getPages().size();
}
paramMap.put("PREVIOUS_PAGE_NUMBER", prevPageNumber);
JasperPrint jasperPrint2 = JasperFillManager.fillReport(report2, paramMap);