1
votes

I am generating PDF using Apache FOP XSL file format.

My requirements are

  • Tabular data in PDF
  • Table size is large so the Same table extended to multiple pages (width-wise, few columns in first page others are on the next page)
  • Page 1 has 3 columns (C1, C2, C3)
  • Page 2 has 5 columns (C4, C5, C6, C7, C8)
  • Few cells may have multiline data

Problem description:

  • When Page-2 has multiline data for Row 4, Column 4, so its row height increased as per content enter image description here
  • But in Page-1 row 4 has row height as a single line.

enter image description here

I want to have the same row height across all pages of the same table when any cell data is multiline of any page.

Here is XSL file if needed:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
    version="1.0">

  <!-few params declaration->

    <xsl:template match="/rs">
        <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
            <fo:layout-master-set>
                <fo:simple-page-master master-name="data-template-1" page-height="11.0in" page-width="17.0in"
                                       margin-top="0.5in" margin-bottom="1.0in" margin-left="0.5in"
                                       margin-right="0.5in">
                    <fo:region-body margin-top="1.5in" margin-bottom="0.8in"/>
                    <fo:region-before extent="0.7in"/>
                    <fo:region-after/>
                </fo:simple-page-master>
                <fo:simple-page-master master-name="data-template-2" page-height="11.0in" page-width="17.0in"
                                       margin-top="0.5in" margin-bottom="1.0in" margin-left="0.5in"
                                       margin-right="0.5in">
                    <fo:region-body margin-top="1.5in" margin-bottom="0.8in"/>
                    <fo:region-before extent="0.7in"/>
                    <fo:region-after/>
                </fo:simple-page-master>
            </fo:layout-master-set>

            <xsl:for-each select="rb">
                <xsl:variable name="current-initial-page-number" select="$param.initialPageNumber + (position() * $pagesPerTable)" />
                <fo:page-sequence master-reference="data-template-1" initial-page-number="{$current-initial-page-number}"
                                  font-size="{$cdrFontSize}" font-family="{$cdrFontFamily}" line-height="10.2pt">
                    
                    
                    <fo:flow flow-name="xsl-region-body">
                        <fo:table table-layout="fixed" width="100%" space-after.optimum="{$cdrInfoTableSpaceAfter}" border-width="0.4mm" border-style="solid">
                            <fo:table-column column-width="23.1mm"/>
                            <fo:table-column column-width="23.1mm"/>
                            <fo:table-column column-width="18.9mm"/>
                            
                            <fo:table-header text-align="center" display-align="center">
                                <fo:table-row font-weight="bold" background-color="rgb(230,230,230)">
                                    <xsl:call-template name="cdr_table_cell">
                                        <xsl:with-param name="cellValue" select="'C1'"/>
                                    </xsl:call-template>
                                    <xsl:call-template name="cdr_table_cell">
                                        <xsl:with-param name="cellValue" select="'C2'"/>
                                    </xsl:call-template>
                                    <xsl:call-template name="cdr_table_cell">
                                        <xsl:with-param name="cellValue" select="'C3"/>
                                    </xsl:call-template>
                                    
                                </fo:table-row>
                            </fo:table-header>

                            <fo:table-body>
                                <xsl:for-each select="r">
                                    <fo:table-row text-align="left" display-align="before">
                                        <xsl:call-template name="cdr_table_cell">
                                            <xsl:with-param name="cellValue" select="c[@n='C1']"/>
                                        </xsl:call-template>
                                        <xsl:call-template name="cdr_table_cell">
                                            <xsl:with-param name="cellValue" select="c[@n='C12']"/>
                                        </xsl:call-template>
                                        <xsl:call-template name="cdr_table_cell">
                                            <xsl:with-param name="cellValue" select="c[@n='C3']"/>
                                        </xsl:call-template>
                                        
                                    </fo:table-row>
                                </xsl:for-each>
                            </fo:table-body>
                        </fo:table>
                    </fo:flow>
                </fo:page-sequence>
                <fo:page-sequence master-reference="data-template-2"
                                  font-size="{$cdrFontSize}" font-family="{$cdrFontFamily}" line-height="10.2pt">
                    
                    <fo:flow flow-name="xsl-region-body">
                        <fo:table table-layout="fixed" width="100%" space-after.optimum="{$cdrInfoTableSpaceAfter}" border-width="0.4mm" border-style="solid">
                            <fo:table-column column-width="88.2mm"/>
                            <fo:table-column column-width="88.2mm"/>
                            <fo:table-column column-width="48.3mm"/>
                            <fo:table-column column-width="23.1mm"/>
                            <fo:table-column column-width="54.6mm"/>
                            <fo:table-header text-align="center" display-align="center">
                                <fo:table-row font-weight="bold" background-color="rgb(230,230,230)">
                                    <xsl:call-template name="cdr_table_cell">
                                        <xsl:with-param name="cellValue" select="'C4'"/>
                                    </xsl:call-template>
                                    <xsl:call-template name="cdr_table_cell">
                                        <xsl:with-param name="cellValue" select="'C5'"/>
                                    </xsl:call-template>
                                    <xsl:call-template name="cdr_table_cell">
                                        <xsl:with-param name="cellValue" select="'C6'"/>
                                    </xsl:call-template>
                                    <xsl:call-template name="cdr_table_cell">
                                        <xsl:with-param name="cellValue" select="'C7'"/>
                                    </xsl:call-template>
                                    <xsl:call-template name="cdr_table_cell">
                                        <xsl:with-param name="cellValue" select="'C8'"/>
                                    </xsl:call-template>
                                </fo:table-row>R
                            </fo:table-header>

                            <fo:table-body>
                                <xsl:for-each select="r">
                                    <fo:table-row text-align="left" display-align="before">
                                        <xsl:call-template name="cdr_table_cell">
                                            <xsl:with-param name="cellValue" select="c[@n='C4']"/>
                                        </xsl:call-template>
                                        <xsl:call-template name="cdr_table_cell">
                                            <xsl:with-param name="cellValue" select="c[@n='C5']"/>
                                        </xsl:call-template>
                                        <xsl:call-template name="cdr_table_cell">
                                            <xsl:with-param name="cellValue" select="c[@n='C6']"/>
                                        </xsl:call-template>
                                        <xsl:call-template name="cdr_table_cell">
                                            <xsl:with-param name="cellValue" select="c[@n='C7']"/>
                                        </xsl:call-template>
                                        <xsl:call-template name="cdr_table_cell">
                                            <xsl:with-param name="cellValue" select="c[@n='C8']"/>
                                        </xsl:call-template>
                                    </fo:table-row>
                                </xsl:for-each>
                            </fo:table-body>
                        </fo:table>
                    </fo:flow>
                </fo:page-sequence>
            </xsl:for-each>
        </fo:root>
    </xsl:template>

    <xsl:template name="cdr_table_cell">
        <xsl:param name="cellValue"/>
        <fo:table-cell border-width="0.4mm" border-style="solid">
            <fo:block-container overflow="hidden">
                <fo:block margin-left="0.5mm" margin-top="0.3mm">
                    <xsl:call-template name="zero_width_space_1">
                        <xsl:with-param name="data" select="$cellValue"/>
                    </xsl:call-template>
                </fo:block>
            </fo:block-container>
        </fo:table-cell>
    </xsl:template>

    <!-- The following templates are used to add empty space character to data, so that FOP can break (wrap) the word -->
    <xsl:template name="zero_width_space_1">
        <xsl:param name="data"/>
        <xsl:param name="counter" select="0"/>
        <xsl:choose>
            <xsl:when test="$counter &lt;= string-length($data)">
                <xsl:value-of select='concat(substring($data,$counter,1),"&#8203;")'/>
                <xsl:call-template name="zero_width_space_2">
                    <xsl:with-param name="data" select="$data"/>
                    <xsl:with-param name="counter" select="$counter+1"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="'&#160;'"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="zero_width_space_2">
        <xsl:param name="data"/>
        <xsl:param name="counter"/>
        <xsl:value-of select='concat(substring($data,$counter,1),"&#8203;")'/>
        <xsl:call-template name="zero_width_space_1">
            <xsl:with-param name="data" select="$data"/>
            <xsl:with-param name="counter" select="$counter+1"/>
        </xsl:call-template>
    </xsl:template>
</xsl:stylesheet>

What I don't want

  • Fixed row height as it wastes page space even if all data is accumulated in a single line.
1

1 Answers

2
votes

Format the full table twice: once for each page.

For the first copy of the table, make everything after column 3 be white or transparent.

For the second copy of the table, make everything in columns 1 to 3 be white or transparent and also add a negative margin on the table (and set it back to 0 in the table cells) so that columns 1 to 3 are off the left side of the page.

Note that if you were using AH Formatter, you could use the Spread Page Master extension (see https://www.antenna.co.jp/AHF/help/v70e/ahf-spread.html) and make a region that spans both pages.