javabirtpage-numbering

BIRT Separate page count for each table


Preface: I've found a question similar to the problem I have, but I'm not attempting to use "Group" for the separation.


I have a BIRT's rptdesign file which has three tables inside, I would like to separate page count for each table, the following pictures illustrate the comparison.

Default Result: Show "current page/total page" for the entire report. enter image description here

Separate Page Count Result: Show "current page/total page" for each table. enter image description here


Solution is down below the answer's block.


Solution

  • BIRT do not support this feature by default. Therefore, we must do it manually by hard-coded it. According to the official document, we need to create some event handlers so as to alter report content.

    There are two phase for BIRT to produce the result.

    1. Generation phase will consume the rptdesign file and creates an report document.
    2. Presentation phase uses the report document to render to HTML or PDF.

    During Generation phase, BIRT will generate each page one by one, because of this mechanism, it won't actually know what's the total pages of this table it is converting right now. So we can't just create event handlers in Generation phase to solve this problem, we also need to create event handlers that belongs to Presentation phase in order to render the page count by ourselves.

    So the whole process will be

    1. Create Generation phase's event handlers to count the total pages of each table.
    2. Share the counting data from Generation phase to Presentation phase.
    3. Create Presentation phase's event handlers and render the counting data to the output report content.

    Details:

    1. Create onCreate events inside each table tag to set the tableName for each table.
    <table name="A" id="8356">
        <method name="onCreate"><![CDATA[tableName = 'A';]]></method>
        ...
    </table>
    
    <table name="B" id="8861">
        <method name="onCreate"><![CDATA[tableName = 'B';]]></method>
        ...
    </table>
    
    <table name="C" id="9405">
        <method name="onCreate"><![CDATA[tableName = 'C';]]></method>
        ...
    </table>
    
    1. Create beforeFactory event and onPageEnd event for storing and updating the counting data.
    <?xml version="1.0" encoding="UTF-8"?>
    <report xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23" id="1">
        <property name="createdBy">Eclipse BIRT Designer Version 4.8.0.v201806261756</property>
        <property name="units">in</property>
        <method name="beforeFactory"><![CDATA[
                reportContext.setPersistentGlobalVariable("tablePageMap", new java.util.HashMap());
                reportContext.setPersistentGlobalVariable("currentPageNumber", new java.lang.Integer(1));
        ]]></method>
        
        <method name="onPageEnd"><![CDATA[
                var tablePageNumber = reportContext.getPersistentGlobalVariable("tablePageMap").get(tableName);
                if(tablePageNumber === null) {
                    reportContext.getPersistentGlobalVariable("tablePageMap").put(tableName, 1);
                } else {
                    reportContext.getPersistentGlobalVariable("tablePageMap").put(tableName, parseInt(tablePageNumber) + 1);
                }
        ]]></method>
        ...
    </report>
    
    1. Render the counting data to the relative cell.

    For "current page cell" (Change the key when getting data out from tablePageMap)

    <cell id="8181">
        <property name="textAlign">center</property>
        <auto-text id="8182">
            <method name="onRender"><![CDATA[
                var tablePageNumber = reportContext.getPersistentGlobalVariable("tablePageMap").get("A");
                var currentPageNumber = reportContext.getPersistentGlobalVariable("currentPageNumber");
                if(currentPageNumber <= tablePageNumber) {
                    this.text = java.lang.Integer.toString(currentPageNumber);
                }
                if (currentPageNumber == tablePageNumber) {
                    reportContext.setPersistentGlobalVariable("currentPageNumber", java.lang.Integer(1));
                } else {
                    reportContext.setPersistentGlobalVariable("currentPageNumber", new java.lang.Integer(parseInt(currentPageNumber) + 1));
                }
            ]]></method>
        </auto-text>
    </cell>
    

    For "total page" (Change the key when getting data out from tablePageMap)

    <cell id="8185">
        <property name="textAlign">center</property>
        <auto-text id="8186">
            <method name="onRender"><![CDATA[
                    var tablePageNumber = reportContext.getPersistentGlobalVariable("tablePageMap").get("A");
                    this.text = java.lang.Integer.toString(tablePageNumber);
            ]]></method>
        </auto-text>
    </cell>
    

    You should change the id number above to the number that fit your rptdesign file.

    Note: This requires 2-phase tasks: RunTask and RenderTask be called sequentially! It doesn't work with RunAndRenderTask!

    That's it! Run the program and check the output result.