带有两个块顶部和底部对齐的单元格的FOP表

时间:2015-06-17 19:03:09

标签: alignment cell xsl-fo apache-fop

我想使用FOP生成如下图所示的表:

desired table output

  • 左列可以有1行或任意数量的行。
  • 右栏中的Block1和Block2可以有1行或任意数行。我希望Block1顶部对齐,Block2底部对齐。

对于正确的专栏,我尝试了这个:

<fo:table-cell number-rows-spanned="$rows-spanned" display-align="after">
    <fo:block>
        Block1 Lorem ipsum
    </fo:block>
    <fo:block>
        Block2 Lorem ipsum bla aaaa
    </fo:block>
</fo:table-cell>

但它将Block1和Block2对齐到底部。

知道如何实现所需的输出吗?

2 个答案:

答案 0 :(得分:1)

(disclosure: I'm a FOP developer, though not very active nowadays)

After some pondering, I've thought of two possible solutions.

Solution 1 (recommended): using two spanning cells

Instead of spanning all the rows with a single cell containing both blocks, span just half the rows with a cell containing Block 1, and then use another row-spanning cell with display-align="after" for Block 2:

        <fo:table width="100%" table-layout="fixed">
            <fo:table-column column-width="50%"/>
            <fo:table-column column-width="50%"/>
            <fo:table-body>
                <fo:table-row>
                    <fo:table-cell border="1pt solid #000000">
                        <fo:block>header</fo:block>
                    </fo:table-cell>
                    <fo:table-cell border="1pt solid #000000" border-bottom="none" number-rows-spanned="6">
                        <fo:block color="red">Block 1 Lorem ipsum</fo:block>
                    </fo:table-cell>
                </fo:table-row>
                <!-- ... 5 more rows ... -->
                <fo:table-row>
                    <fo:table-cell border="1pt solid #000000">
                        <fo:block>item 6</fo:block>
                    </fo:table-cell>
                    <fo:table-cell border="1pt solid #000000" border-top="none" number-rows-spanned="5" display-align="after">
                        <fo:block color="blue">Block 2 Lorem ipsum bla aaaa</fo:block>
                    </fo:table-cell>
                </fo:table-row>
                <!-- ... the remaining 4 rows ... -->
            </fo:table-body>
        </fo:table>

Pros:

  • cleaner solution
  • no overlapping problems if there are few rows and the text blocks are several lines long

Cons:

  • the stylesheet to produce this would be more complicated (you have got to produce two row-spanning cells in the right row, taking into account that the number of rows could be odd / even)

Solution 2: using an extra column and margin tricks

You can define the table to have 3 columns, put Block 1 in a cell spanning all rows in column #2 and Block 2 spanning all rows in column #3, and creatively use margins to "move" Block 2 in the desired location:

        <fo:table width="12cm" table-layout="fixed">
            <fo:table-column column-width="4cm"/>
            <fo:table-column column-width="4cm"/>
            <fo:table-column column-width="4cm"/>
            <fo:table-body>
                <fo:table-row>
                    <fo:table-cell border="1pt solid #000000">
                        <fo:block>header</fo:block>
                    </fo:table-cell>
                    <fo:table-cell border="1pt solid #000000" number-rows-spanned="11">
                        <fo:block color="red">Block 1 Lorem ipsum</fo:block>
                    </fo:table-cell>
                    <fo:table-cell number-rows-spanned="11" display-align="after">
                        <!-- use margins to "push" the block in the previous column -->
                        <fo:block margin-left="-4cm" margin-right="4cm" color="blue">Block 2 Lorem ipsum bla aaaa</fo:block>
                    </fo:table-cell>
                </fo:table-row>
                <!-- ... the other 10 rows ... -->
            </fo:table-body>
        </fo:table>

Pro:

  • simpler template to produce this, as you have to care about column #2 and #3 in the first row only

Cons:

  • if there are few rows and long blocks of text, they could overlap
  • should the table have a page break inside it, both text would appear on the first page (as they are both in the first row)
  • this is probably a dirty trick, so I would not recommend doing this (I tested it with FOP 1.1 and 2.0 and it works, with an INFO message about the table being larger than the available space)

答案 1 :(得分:0)

如果你知道身高,你可以这样做

<fo:table-cell text-align="left" height="5cm">
<fo:block>
    <fo:block-container height="25mm">
        <fo:block xsl:use-attribute-sets="myBorder">
            Block1 Lorem ipsum
        </fo:block>
    </fo:block-container>
    <fo:block-container height="25mm" xsl:use-attribute-sets="myBorder" display-align="after">
        <fo:block xsl:use-attribute-sets="myBorder" vertical-align="bottom" display-align="after">
             Lorem ipsum bla aaaa
        </fo:block>
    </fo:block-container>
</fo:block>