Java 在导出中合并多个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

在聊天室收到关于如何处理jasper报告中的页码的问题和答案后,我决定通过此问答

使用

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);