adam5990
adam5990

Reputation: 366

Is it possible to get a running total to display in XSLT/XSL FO?

I am trying to format a report and I have tables that will span multiple pages with various items/fees, and what i would like to do ideally is to display a running total for each page in the table footer, basically i want the sum of the values in my table from the current page back to the first page to display at the bottom. Is there any way to achieve this?

<fo:table width="100%" border-style="groove" border-width="2pt" background-repeat="repeat">
  <fo:table-column column-width="5%" />
  <fo:table-column column-width="60%" />
  <fo:table-column column-width="5%" />
  <fo:table-column column-width="7.5%" />
  <fo:table-column column-width="7.5%" />
  <fo:table-column column-width="7.5%" />
  <fo:table-column column-width="7.5%" />
  <fo:table-footer border-top-style="dashed" border-bottom-style="dashed">
    <fo:table-cell display-align="center">
    </fo:table-cell>
    <fo:table-cell display-align="center">
      <fo:block text-align="center">
        Page <fo:page-number/>
        <xsl:text> OF </xsl:text>
        <fo:page-number-citation ref-id="end" />
      </fo:block>
    </fo:table-cell>
    <fo:table-cell display-align="center">
    </fo:table-cell>
    <fo:table-cell display-align="center">
    </fo:table-cell>
    <fo:table-cell display-align="center">
    </fo:table-cell>
    <fo:table-cell display-align="center">
      <fo:block text-align="end">
        Page Total:
      </fo:block>
    </fo:table-cell>
    <fo:table-cell display-align="center">
    </fo:table-cell>
  </fo:table-footer>
  <fo:table-body>
    <xsl:for-each select="/receipt_invoice/details/product_lot">
      <xsl:variable name="untitled" select="." />
      <fo:table-row>
        <fo:table-cell border-style="solid" border-width="1pt" border-color="black" padding="2pt" background-repeat="repeat" display-align="center">
          <fo:block text-align="right">
            <fo:block>
              <xsl:value-of select="lot/quantity" />
            </fo:block>
          </fo:block>
        </fo:table-cell>
        <fo:table-cell border-style="solid" border-width="1pt" border-color="black" padding="2pt" background-repeat="repeat" display-align="center">
          <fo:block>
            <fo:table width="100%" border-style="none" border-width="2pt" background-repeat="repeat">
              <fo:table-column/>
              <fo:table-column/>
              <fo:table-body>
                <fo:table-row>
                  <fo:table-cell border-style="none" border-width="2pt" padding="2pt" background-repeat="repeat" display-align="before">
                    <fo:block>
                      <fo:block>
                        <xsl:value-of select="product/code" />
                      </fo:block>
                      <fo:block>
                        Lot Qty:
                        <xsl:value-of select="lot/quantity" />
                      </fo:block>
                      <fo:block>
                        <xsl:text>
                          &#xA0;
                        </xsl:text>
                      </fo:block>
                      <fo:block>
                        <xsl:value-of select="lot/identifier" />
                      </fo:block>
                      <fo:block>
                        <xsl:value-of select="lot/lot_components/component/label" />
                      </fo:block>
                      <fo:block>
                        <xsl:value-of select="lot/lot_components/component/value" />
                      </fo:block>
                    </fo:block>
                  </fo:table-cell>
                  <fo:table-cell border-style="none" border-width="2pt" padding="2pt" background-repeat="repeat" display-align="before">
                    <fo:block>
                      <fo:block>
                        <xsl:value-of select="product/first_description" />
                      </fo:block>
                      <fo:block>
                        <xsl:value-of select="lot/csd/csd_line" />
                      </fo:block>
                      <fo:block>
                        <xsl:value-of select="lot/csd/set_description" />
                      </fo:block>
                      <fo:block>
                        <xsl:value-of select="lot/lot_components/component/label" />
                      </fo:block>
                    </fo:block>
                  </fo:table-cell>
                </fo:table-row>
              </fo:table-body>
            </fo:table>
            Line Number:
            <xsl:value-of select="line_number" />
          </fo:block>
        </fo:table-cell>
        <fo:table-cell border-style="solid" border-width="1pt" border-color="black" padding="2pt" background-repeat="repeat" display-align="center">
          <fo:block text-align="center">
            <fo:block>
              <xsl:value-of select="product/unit_of_measure" />
            </fo:block>
          </fo:block>
        </fo:table-cell>
        <fo:table-cell border-style="solid" border-width="1pt" border-color="black" padding="2pt" background-repeat="repeat" display-align="center">
          <fo:block text-align="center">
            <fo:block>
              <xsl:value-of select="stock_charges/storage_rate" />
            </fo:block>
          </fo:block>
        </fo:table-cell>
        <fo:table-cell border-style="solid" border-width="1pt" border-color="black" padding="2pt" background-repeat="repeat" display-align="center">
          <fo:block text-align="center">
            <fo:block>
              <xsl:value-of select="stock_charges/storage_amount" />
            </fo:block>
          </fo:block>
        </fo:table-cell>
        <fo:table-cell border-style="solid" border-width="1pt" border-color="black" padding="2pt" background-repeat="repeat" display-align="center">
          <fo:block text-align="center">
            <fo:block>
              <xsl:value-of select="stock_charges/handling_rate" />
            </fo:block>
          </fo:block>
        </fo:table-cell>
        <fo:table-cell border-style="solid" border-width="1pt" border-color="black" padding="2pt" background-repeat="repeat" display-align="center">
          <fo:block text-align="center">
            <fo:block>
              <xsl:value-of select="stock_charges/handling_amount" />
            </fo:block>
          </fo:block>
        </fo:table-cell>
      </fo:table-row>
    </xsl:for-each>
  </fo:table-body>
</fo:table>

Revision:

So I have decided to use a page footer to display the subtotal on each page, and have set up a marker in my table that simply returns the grand total just to test it out, but now what i was think was that i could try to somehow get the position in my xml file the node was taken from and use something like...

<xsl:value-of select="sum(preceding::value[the_position]"/> 

Where value would actually be the name of the charge being totaled up, is this something that could work? If have been trying different things but I am uncertain of the syntax and how to return the position.

Upvotes: 0

Views: 1311

Answers (1)

Kevin Brown
Kevin Brown

Reputation: 8877

For completeness, posting the description of the solution as an answer.

If your rows are of pretty regular height, you can use sum() function over all previous nodes in your table structure as you output rows and put that running subtotal as a table/table row inside a marker for the footer of the page as a single row table. Retrieve the marker into the page footer (not the table-footer with retrieve-table-marker) using the last one on the page, then clear the marker. Careful sizing and you can get it to look just like it is a table footer and you can clear that marker at the end of the table so that it does not appear on other pages. For the table end, just output the totals.

It may not work with complex tables, especially where there are multi-line rows and keeps on those rows as the table may not reach the footer.

This overcomes two issues (1) you do not need table-markers as many FO engines do not support them (actually there are good reasons for this as they are much more problematic than you think if the content being retrieved could have a large, variable height). And (2) using table-markers can run into issues at the end of the table inside that footer where you may not want it (although you can clear the marker at the last row).

Upvotes: 1

Related Questions