XSL表格无固定行数时实现每页小计的技术咨询
跨页表格每页小计实现问题
我有一个可跨多页显示的表格,希望为每页添加小计。目前能通过preceding-siblings获取到当前页之前的累计小计,但无法获取当前页本身的小计。找到过一个基于XSLT 1.0的方案,但该方案依赖固定行数,而我的场景中行数提前未知且每页行数可能变化。
以下是我的部分XSL代码:
<fo:static-content flow-name="footer"> <fo:block-container height="10mm"> <xsl:variable name="vStart" ><fo:retrieve-marker retrieve-class-name="RunningSubTotal" retrieve-boundary="page" retrieve-position="first-starting-within-page" /> </xsl:variable> <xsl:variable name="vEnd" ><fo:retrieve-marker retrieve-class-name="RunningSubTotal" retrieve-boundary="page" retrieve-position="last-ending-within-page" /> </xsl:variable> <fo:block font-size="8pt">vStart:<xsl:copy-of select="$vStart" /></fo:block> <fo:block font-size="8pt">vEnd:<xsl:copy-of select="$vEnd" /></fo:block> <fo:block font-size="8pt">diff (vEnd - vStart):</fo:block> </fo:block-container> </fo:static-content>
现咨询三个问题:
- 是否可以对未知行数的行进行求和?
- 能否对标记值执行减法运算?
- 是否可以获取每页的行数?
问题解答
1. 可以对未知行数的行进行求和
在XSLT 1.0结合XSL-FO的场景下,完全可以实现未知行数的每页小计,核心是运行总计+标记机制,不需要依赖固定行数:
- 在表格每一行中插入
fo:marker,存储从第一行到当前行的累计总和(纯数值,不要带格式化符号)。 - 在页脚静态内容中,用
fo:retrieve-marker分别获取当前页第一行的累计值(first-starting-within-page)和最后一行的累计值(last-ending-within-page)。 - 当前页小计 = 最后一行累计值 - (第一行累计值 - 当前页第一行的数值),或者如果第一行的累计值是不包含自身的前置总和,直接用最后累计值减第一累计值即可,具体逻辑根据你累计值的计算方式调整。
这种方式完全适配行数未知、每页行数动态变化的场景。
2. 可以对标记值执行减法运算
只要标记中存储的是纯数值,就能执行减法运算,关键是把标记内容转为数字类型:
- 先确保
fo:marker里只放数值,比如不要包含$或逗号这类格式化字符。 - 在XSLT 1.0中用
number()函数将标记内容转为数字,再计算差值:<xsl:variable name="startNum" select="number($vStart)" /> <xsl:variable name="endNum" select="number($vEnd)" /> <fo:block font-size="8pt">diff (vEnd - vStart):<xsl:value-of select="$endNum - $startNum" /></fo:block> - 注意边界情况:如果是第一页,第一行的累计值就是自身数值,此时差值就是当前页所有行的总和;如果某页只有一行,差值为0,需要额外判断直接显示该行数值。
3. 可以获取每页的行数
同样通过标记机制实现:
- 在表格每一行的
fo:marker中存储当前行的序号(用position()获取递增行号)。 - 在页脚中,用
fo:retrieve-marker获取当前页第一行和最后一行的行号,转为数字后计算:
行内标记示例:
页脚计算示例:<fo:table-row> <fo:table-cell> <fo:block> <fo:marker marker-class-name="RowNumber"> <xsl:value-of select="position()" /> </fo:marker> <!-- 单元格内容 --> </fo:block> </fo:table-cell> </fo:table-row><xsl:variable name="firstRow" select="number(fo:retrieve-marker(retrieve-class-name='RowNumber', retrieve-boundary='page', retrieve-position='first-starting-within-page'))" /> <xsl:variable name="lastRow" select="number(fo:retrieve-marker(retrieve-class-name='RowNumber', retrieve-boundary='page', retrieve-position='last-ending-within-page'))" /> <fo:block font-size="8pt">当前页行数:<xsl:value-of select="$lastRow - $firstRow + 1" /></fo:block>
内容的提问来源于stack exchange,提问作者Catia
相关产品推荐
相关产品推荐

