Search manual:

- Main page
- Introduction
- Hello, world!
- Basics
  - How to write the layout
  - Structure of the data file and the layout rules
  - Outputting objects
  - Grid
  - Areas on the page (PositioningArea)
  - File organization
  - Hyphenation / language settings
  - Using fonts
  - Text formats
  - Text formatting
  - Colors
- Programming
- Image inclusion
- Tables
- Advanced topics
  - Bookmarks
  - Creation of XML structures
  - Print output / crop marks
  - Using CSS with the speedata Publisher
  - Groups (virtual objects)
  - Virtual pages
  - Rotation of contents
  - Sorting data
  - Wrap around images
  - Page types
  - Starting the Publisher via the Hotfolder
  - Lua-Filter / pre-processing
  - Schema validation
  - Quality assurance and PDF comparison
  - Troubleshooting / Debugging
  - Server mode (REST API)
  - Control of the layout when calling the Publisher
  - Create and use images with MetaPost
- Cookbook
  - Thumb index
  - Embed multipage PDF files
  - Layout optimization using groups
  - Imitate bulleted lists
  - Automatically generated directories
  - Create table of contents in one go
  - Page numbers: Page x of y
- Installation instructions
- File name in the Publisher
- speedata Publisher defaults
- Running the speedata publisher on the command line
- How to configure the speedata publisher
- Lenghts and units
- XPath- and Layoutfunctions
- Internal variables
- Associate XML editor with schema
  - Visual Studio Code
  - OxygenXML
- Changelog
- Glossary
- Compatibility with other software
- Command reference
  - A
  - Action
  - AddSearchpath
  - AtPageCreation
  - AtPageShipout
  - AttachFile
  - Attribute
  - B
  - Barcode
  - Bold
  - BoldItalic
  - Bookmark
  - Box
  - Br
  - Case
  - Circle
  - ClearPage
  - Color
  - Column
  - Columns
  - Compatibility
  - Contents
  - Copy-of
  - DefineColor
  - DefineColorprofile
  - DefineFontalias
  - DefineFontfamily
  - DefineGraphic
  - DefineMatter
  - DefineTextformat
  - Element
  - Fallback
  - Fontface
  - ForAll
  - Frame
  - Grid
  - Group
  - Groupcontents
  - HSpace
  - Hyphenation
  - I
  - Image
  - Include
  - Initial
  - InsertPages
  - Italic
  - Layout
  - Li
  - LoadDataset
  - LoadFontfile
  - Loop
  - Makeindex
  - Margin
  - Mark
  - Message
  - NewPage
  - NextFrame
  - NextRow
  - NoBreak
  - Ol
  - Options
  - Otherwise
  - Output
  - Overlay
  - Pageformat
  - Pagetype
  - Paragraph
  - PDFOptions
  - PlaceObject
  - Position
  - PositioningArea
  - PositioningFrame
  - ProcessNode
  - Record
  - Regular
  - Rule
  - SaveDataset
  - SavePages
  - SetGrid
  - SetVariable
  - SortSequence
  - Stylesheet
  - Span
  - Sub
  - Sup
  - Switch
  - Table
  - TableNewPage
  - Tablefoot
  - Tablehead
  - Tablerule
  - Td
  - Text
  - Textblock
  - Tr
  - Trace
  - Transformation
  - U
  - Ul
  - Until
  - URL
  - Value
  - VSpace
  - While

Version 4.10.0
Search manual

- Main page
- Introduction
- Hello, world!
- Basics
  - How to write the layout
  - Structure of the data file and the layout rules
  - Outputting objects
  - Grid
  - Areas on the page (PositioningArea)
  - File organization
  - Hyphenation / language settings
  - Using fonts
  - Text formats
  - Text formatting
  - Colors
- Programming
- Image inclusion
- Tables
- Advanced topics
  - Bookmarks
  - Creation of XML structures
  - Print output / crop marks
  - Using CSS with the speedata Publisher
  - Groups (virtual objects)
  - Virtual pages
  - Rotation of contents
  - Sorting data
  - Wrap around images
  - Page types
  - Starting the Publisher via the Hotfolder
  - Lua-Filter / pre-processing
  - Schema validation
  - Quality assurance and PDF comparison
  - Troubleshooting / Debugging
  - Server mode (REST API)
  - Control of the layout when calling the Publisher
  - Create and use images with MetaPost
- Cookbook
  - Thumb index
  - Embed multipage PDF files
  - Layout optimization using groups
  - Imitate bulleted lists
  - Automatically generated directories
  - Create table of contents in one go
  - Page numbers: Page x of y
- Installation instructions
- File name in the Publisher
- speedata Publisher defaults
- Running the speedata publisher on the command line
- How to configure the speedata publisher
- Lenghts and units
- XPath- and Layoutfunctions
- Internal variables
- Associate XML editor with schema
  - Visual Studio Code
  - OxygenXML
- Changelog
- Glossary
- Compatibility with other software
- Command reference
  - A
  - Action
  - AddSearchpath
  - AtPageCreation
  - AtPageShipout
  - AttachFile
  - Attribute
  - B
  - Barcode
  - Bold
  - BoldItalic
  - Bookmark
  - Box
  - Br
  - Case
  - Circle
  - ClearPage
  - Color
  - Column
  - Columns
  - Compatibility
  - Contents
  - Copy-of
  - DefineColor
  - DefineColorprofile
  - DefineFontalias
  - DefineFontfamily
  - DefineGraphic
  - DefineMatter
  - DefineTextformat
  - Element
  - Fallback
  - Fontface
  - ForAll
  - Frame
  - Grid
  - Group
  - Groupcontents
  - HSpace
  - Hyphenation
  - I
  - Image
  - Include
  - Initial
  - InsertPages
  - Italic
  - Layout
  - Li
  - LoadDataset
  - LoadFontfile
  - Loop
  - Makeindex
  - Margin
  - Mark
  - Message
  - NewPage
  - NextFrame
  - NextRow
  - NoBreak
  - Ol
  - Options
  - Otherwise
  - Output
  - Overlay
  - Pageformat
  - Pagetype
  - Paragraph
  - PDFOptions
  - PlaceObject
  - Position
  - PositioningArea
  - PositioningFrame
  - ProcessNode
  - Record
  - Regular
  - Rule
  - SaveDataset
  - SavePages
  - SetGrid
  - SetVariable
  - SortSequence
  - Stylesheet
  - Span
  - Sub
  - Sup
  - Switch
  - Table
  - TableNewPage
  - Tablefoot
  - Tablehead
  - Tablerule
  - Td
  - Text
  - Textblock
  - Tr
  - Trace
  - Transformation
  - U
  - Ul
  - Until
  - URL
  - Value
  - VSpace
  - While

- Dieses Handbuch auf Deutsch

# Page numbers: Page x of y

There are two ways to get the last page number. The first is the simple way and is recommended. The second one was the way to go until version 3.9.26 and can be used as a reference to store other data needed for subsequent runs.

## The simple way: `$_lastpage`

Just use the internal variable `$_lastpage` to get the pagenumber of the last page of the previous run. That means that you have to use at least two runs to get the correct value for the variable. This works since version 3.9.26.

## The more complicated way

To specify the length of the document in pages, a second pass of the Publisher is necessary: At the end of the first pass, the current (= last) page number is stored, which can then be used in subsequent passes.

The following example creates some pages with output in the form Page 1 of ??. This serves as a basis for the additions.

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

      <Record element="data">
        <!-- ?? is a placeholder that gets overridden -->
        <SetVariable variable="maxpages" select="'??'"/>

        <Loop select="10" variable="i">
          <PlaceObject>
            <Textblock>
              <Paragraph>
                <Value
                  select="concat('Page ', sd:current-page(), ' of ', $maxpages )"/>
              </Paragraph>
            </Textblock>
          </PlaceObject>
          <SetVariable variable="lastpage" select="sd:current-page()"/>
          <ClearPage/>
        </Loop>
      </Record>
    </Layout>

At the end of the last page the information can be cached for the next run using `<SaveDataset>`:

    <SetVariable variable="attrPagenumber">
      <Attribute name="numberofpages" select="$lastpage"/>
    </SetVariable>
    <SaveDataset
      name="pagecount"
      elementname="pageinfo"
      attributes="$attrPagenumber"/>

`<SaveDataset>` expects an XML structure at attributes can be stored in the element `<Attributes>' and, elements in `<Element>', whereby this command can in turn have `<Attributes>' as child elements. This structure is saved to disk as XML and has the following form in this example:

    <pageinfo numberofpages="10" />

At the beginning of the run, the file can now be read in if it exists (i.e. no error is generated in the first run because the file has not yet been created):

    <Record element="data">
      <SetVariable variable="maxpages" select="'??'"/>
      <LoadDataset name="pagecount"/>
      ...

and in addition

    <Record element="pageinfo">
      <SetVariable variable="maxpages" select="@numberofpages"/>
    </Record>

The record 'pageinfo' is called when the XML file 'pagecount' is read. Nothing else is done than overwriting the recently defined variable `maxpages` with the correct content.

The complete example now looks like this:

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

      <!-- only evaluated if the file `pagecount` is found (second run) -->
      <Record element="pageinfo">
        <SetVariable variable="maxpages" select="@numberofpages"/>
      </Record>

      <!-- start of data processing -->
      <Record element="data">
        <SetVariable variable="maxpages" select="'??'"/>
        <LoadDataset name="pagecount"/>
        <Loop select="10" variable="i">
          <PlaceObject>
            <Textblock>
              <Paragraph>
                <Value
                  select="concat('Page ', sd:current-page(), ' of ', $maxpages )"/>
              </Paragraph>
            </Textblock>
          </PlaceObject>
          <SetVariable variable="lastpage" select="sd:current-page()"/>
          <ClearPage/>
        </Loop>
        <!--  Now we know the total number of pages  -->
        <SetVariable variable="attrPagenumber">
          <Attribute name="numberofpages" select="$lastpage"/>
        </SetVariable>
        <SaveDataset
          name="pagecount"
          elementname="pageinfo"
          attributes="$attrPagenumber"/>
      </Record>
    </Layout>

- Create table of contents in one go
- Installation instructions