Version dev

# Simple table with automatic breaking

## Task

An article list is to be output as a price list. The list is longer than one page: the Publisher should find the page break itself, the table head should repeat on every page, and a closing line appears below the table.

## Decision

The automatic table break is the right approach when three things come together:

- The rows are uniform. Every row has the same columns, and the contents should be aligned to each other across all records.
- The break point does not matter. It is irrelevant which article is the last one to fit on a page; the table may even break in the middle of an article group.
- Continuation pages need no special treatment. The repeated head and foot are all it takes.

If one of these conditions does not hold, the path leads elsewhere: with a fixed page design that the content has to fit into, you work with groups and absolute positioning. Running text belongs in `<Output>`/`<Text>` rather than in a table. And if continuation pages need their own logic, you have to portion the table yourself (see Limits).

## Solution

### The data

All how-to guides use the article data of the fictional manufacturer Confixa: article groups (`group`) contain articles (`article`) with article number, dimensions, drive, packaging unit (`pu`) and price per unit. Here is an excerpt; the complete file can be found in the section Complete example:

    <data company="Confixa">
      <group name="Chipboard screws" code="CS" material="steel, zinc plated">
        <article number="CS-3012" dim="3.0 × 12" drive="TX10" pu="1000" price="4.90"/>
        <article number="CS-3016" dim="3.0 × 16" drive="TX10" pu="1000" price="5.20"/>
        <!-- more articles -->
      </group>
      <group name="Wall plugs" code="WP" material="nylon">
        <article number="WP-0525" dim="5 × 25" pu="100" price="2.10"/>
        <!-- more articles -->
      </group>
      <!-- more groups -->
    </data>

### Step 1: The table skeleton

The entry point `data` outputs the table with `<PlaceObject>`. That is all it takes for the breaking: if the table is longer than the space on the page, the Publisher distributes the rows onto the following pages by itself.

    <Record element="data">
      <PlaceObject>
        <Table stretch="max" padding="3pt">
          <!-- head, foot and rows follow in the next steps -->
        </Table>
      </PlaceObject>
    </Record>

`stretch="max"` stretches the table to the full width of the type area, `padding` gives all cells some inner spacing. The Publisher distributes the column widths automatically based on the contents.

### Step 2: The table head repeats by itself

Everything inside `<Tablehead>` is output at the beginning of the table and again after every page break:

    <Tablehead>
      <Tr background-color="lightgray">
        <Td><Paragraph><B><Value>Item no.</Value></B></Paragraph></Td>
        <Td><Paragraph><B><Value>Dimensions</Value></B></Paragraph></Td>
        <Td><Paragraph><B><Value>Drive</Value></B></Paragraph></Td>
        <Td align="right"><Paragraph><B><Value>PU</Value></B></Paragraph></Td>
        <Td align="right"><Paragraph><B><Value>Price in €</Value></B></Paragraph></Td>
      </Tr>
    </Tablehead>

With the attribute `page` you can define different heads for the first page and the following pages (`page="first"` and `page="all"`), for example for a head with the addition “continued”. This is shown in the recipe Continuation head and continuation note.

### Step 3: The rows come from the data

Two nested `<ForAll>` commands create the rows: the outer one iterates over the article groups, the inner one over the articles. Each group starts with a heading row that spans all five columns:

    <ForAll select="group">
      <Tr top-distance="8pt" break-below="no">
        <Td colspan="5" border-bottom="1pt">
          <Paragraph><B><Value select="@name"/></B></Paragraph>
        </Td>
      </Tr>
      <ForAll select="article">
        <Tr>
          <Td><Paragraph><Value select="@number"/></Paragraph></Td>
          <Td><Paragraph><Value select="@dim"/></Paragraph></Td>
          <Td><Paragraph><Value select="@drive"/></Paragraph></Td>
          <Td align="right"><Paragraph><Value select="@pu"/></Paragraph></Td>
          <Td align="right"><Paragraph><Value select="@price"/></Paragraph></Td>
        </Tr>
      </ForAll>
    </ForAll>

`top-distance` adds some air before each group heading, `border-bottom` draws the line below it. With `break-below="no"` the automatic breaking can be controlled row by row: the page must not break directly below this row, so a group heading is never left behind on its own at the end of a page. The wall plugs have no `drive` attribute; the cell simply stays empty.

### Step 4: The table foot

`<Tablefoot>` is output at the end of every page, repeated just like the head:

    <Tablefoot>
      <Tablerule rulewidth="0.5pt"/>
      <Tr>
        <Td colspan="5" align="right">
          <Paragraph><Value>Net prices per PU</Value></Paragraph>
        </Td>
      </Tr>
    </Tablefoot>

### Complete example

To reproduce the result, put the two files `layout.xml` and `data.xml` into an empty directory and run `sp` there. The runnable project is also available in the examples repository.

    <Layout xmlns="urn:speedata.de:2009/publisher/en"
      xmlns:sd="urn:speedata:2009/publisher/functions/en">

      <Record element="data">
        <PlaceObject>
          <Table stretch="max" padding="3pt">
            <Tablehead>
              <Tr background-color="lightgray">
                <Td><Paragraph><B><Value>Item no.</Value></B></Paragraph></Td>
                <Td><Paragraph><B><Value>Dimensions</Value></B></Paragraph></Td>
                <Td><Paragraph><B><Value>Drive</Value></B></Paragraph></Td>
                <Td align="right"><Paragraph><B><Value>PU</Value></B></Paragraph></Td>
                <Td align="right"><Paragraph><B><Value>Price in €</Value></B></Paragraph></Td>
              </Tr>
            </Tablehead>
            <Tablefoot>
              <Tablerule rulewidth="0.5pt"/>
              <Tr>
                <Td colspan="5" align="right">
                  <Paragraph><Value>Net prices per PU</Value></Paragraph>
                </Td>
              </Tr>
            </Tablefoot>
            <ForAll select="group">
              <Tr top-distance="8pt" break-below="no">
                <Td colspan="5" border-bottom="1pt">
                  <Paragraph><B><Value select="@name"/></B></Paragraph>
                </Td>
              </Tr>
              <ForAll select="article">
                <Tr>
                  <Td><Paragraph><Value select="@number"/></Paragraph></Td>
                  <Td><Paragraph><Value select="@dim"/></Paragraph></Td>
                  <Td><Paragraph><Value select="@drive"/></Paragraph></Td>
                  <Td align="right"><Paragraph><Value select="@pu"/></Paragraph></Td>
                  <Td align="right"><Paragraph><Value select="@price"/></Paragraph></Td>
                </Tr>
              </ForAll>
            </ForAll>
          </Table>
        </PlaceObject>
      </Record>
    </Layout>

    <data company="Confixa">
      <group name="Chipboard screws" code="CS" material="steel, zinc plated">
        <article number="CS-3012" dim="3.0 × 12" drive="TX10" pu="1000" price="4.90"/>
        <article number="CS-3016" dim="3.0 × 16" drive="TX10" pu="1000" price="5.20"/>
        <article number="CS-3020" dim="3.0 × 20" drive="TX10" pu="1000" price="5.60"/>
        <article number="CS-3516" dim="3.5 × 16" drive="TX15" pu="1000" price="5.40"/>
        <article number="CS-3520" dim="3.5 × 20" drive="TX15" pu="1000" price="5.80"/>
        <article number="CS-3525" dim="3.5 × 25" drive="TX15" pu="1000" price="6.30"/>
        <article number="CS-3530" dim="3.5 × 30" drive="TX15" pu="1000" price="6.90"/>
        <article number="CS-4020" dim="4.0 × 20" drive="TX20" pu="500" price="4.20"/>
        <article number="CS-4025" dim="4.0 × 25" drive="TX20" pu="500" price="4.50"/>
        <article number="CS-4030" dim="4.0 × 30" drive="TX20" pu="500" price="4.90"/>
        <article number="CS-4035" dim="4.0 × 35" drive="TX20" pu="500" price="5.30"/>
        <article number="CS-4040" dim="4.0 × 40" drive="TX20" pu="500" price="5.80"/>
        <article number="CS-4045" dim="4.0 × 45" drive="TX20" pu="500" price="6.20"/>
        <article number="CS-4050" dim="4.0 × 50" drive="TX20" pu="500" price="6.70"/>
        <article number="CS-4525" dim="4.5 × 25" drive="TX25" pu="500" price="4.90"/>
        <article number="CS-4530" dim="4.5 × 30" drive="TX25" pu="500" price="5.30"/>
        <article number="CS-4540" dim="4.5 × 40" drive="TX25" pu="500" price="6.10"/>
        <article number="CS-4550" dim="4.5 × 50" drive="TX25" pu="500" price="6.90"/>
        <article number="CS-4560" dim="4.5 × 60" drive="TX25" pu="500" price="7.80"/>
        <article number="CS-5030" dim="5.0 × 30" drive="TX25" pu="200" price="3.60"/>
        <article number="CS-5040" dim="5.0 × 40" drive="TX25" pu="200" price="4.10"/>
        <article number="CS-5050" dim="5.0 × 50" drive="TX25" pu="200" price="4.70"/>
        <article number="CS-5060" dim="5.0 × 60" drive="TX25" pu="200" price="5.30"/>
        <article number="CS-5070" dim="5.0 × 70" drive="TX25" pu="200" price="5.90"/>
        <article number="CS-5080" dim="5.0 × 80" drive="TX25" pu="200" price="6.60"/>
        <article number="CS-6040" dim="6.0 × 40" drive="TX30" pu="100" price="3.20"/>
        <article number="CS-6060" dim="6.0 × 60" drive="TX30" pu="100" price="4.10"/>
        <article number="CS-6080" dim="6.0 × 80" drive="TX30" pu="100" price="5.00"/>
        <article number="CS-60100" dim="6.0 × 100" drive="TX30" pu="100" price="6.10"/>
        <article number="CS-60120" dim="6.0 × 120" drive="TX30" pu="100" price="7.30"/>
      </group>
      <group name="Wall plugs" code="WP" material="nylon">
        <article number="WP-0525" dim="5 × 25" pu="100" price="2.10"/>
        <article number="WP-0630" dim="6 × 30" pu="100" price="2.40"/>
        <article number="WP-0840" dim="8 × 40" pu="100" price="3.60"/>
        <article number="WP-1050" dim="10 × 50" pu="50" price="3.20"/>
        <article number="WP-1260" dim="12 × 60" pu="25" price="2.90"/>
        <article number="WP-1470" dim="14 × 70" pu="20" price="3.80"/>
      </group>
      <group name="Wedge anchors" code="WA" material="steel, zinc plated">
        <article number="WA-0875" dim="M8 × 75" pu="50" price="12.40"/>
        <article number="WA-0895" dim="M8 × 95" pu="50" price="14.10"/>
        <article number="WA-1090" dim="M10 × 90" pu="25" price="9.80"/>
        <article number="WA-10115" dim="M10 × 115" pu="25" price="11.60"/>
        <article number="WA-12100" dim="M12 × 100" pu="20" price="13.20"/>
        <article number="WA-12140" dim="M12 × 140" pu="20" price="16.40"/>
        <article number="WA-16125" dim="M16 × 125" pu="10" price="15.90"/>
        <article number="WA-16180" dim="M16 × 180" pu="10" price="21.30"/>
      </group>
    </data>

## Limits

- Column widths: The Publisher distributes the widths based on the contents. If columns should get fixed or proportional widths, declare them with `<Columns>`/`<Column>`; this is shown in the recipe Controlling column widths.
- Continuation head and continuation note: If the head on the following pages should read “continued”, or a continuation note should appear at the end of the page, you need page-dependent heads and feet; this is shown in the recipe Continuation head and continuation note.
- Custom logic on continuation pages: If the content of a continuation page depends on the break point (for example with complex continuation images), the automatic mechanism is no longer enough. In that case you portion the data yourself, measure with groups and output one table per portion; this is shown in the recipe Breaking complex tables manually.
- All details about tables: the manual chapter Tables and the reference for `<Table>`, `<Tablehead>` and `<Tablefoot>`.

#### On this page