The question may seem simple but I haven’t been able to find anything related to it:
How to start the page numbering index at a given page?
For example, let’s consider a document composed of a front page, a table of content and then the document’s content itself. How can I start the page numbering at the first section of this document instead of starting it at the first page?
Note that I am not trying not to display the page number (which is trivial) but change which page is considered as the first page.
Below is an example:
import os
from reportlab.lib.pagesizes import A4
from reportlab.platypus import BaseDocTemplate, PageTemplate, Frame, Paragraph, PageBreak, NextPageTemplate
from reportlab.platypus.tableofcontents import TableOfContents
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch # Importing inch unit
class Example(BaseDocTemplate):
def __init__(self, fname, **kwargs):
super().__init__(fname, **kwargs)
frame_example = Frame(self.leftMargin - 0.5*inch,
self.bottomMargin + 0.25*inch,
self.width + 1*inch,
self.height - 0.5*inch,
id='example')
# Define some page templates to display the page number
self.addPageTemplates([PageTemplate(id='front_page', frames=frame_example, onPage=self.doFootingsFrontPage),
PageTemplate(id='other_pages', frames=frame_example, onPage=self.doFootings)])
self.elements = []
# Defining some basic paragrah styles for the example
ps1 = ParagraphStyle(fontName='Helvetica', fontSize=14, name='frontPage_PS',
leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16)
ps2 = ParagraphStyle(fontName='Helvetica', fontSize=12, name='header_PS',
leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16)
ps3 = ParagraphStyle(fontName='Helvetica', fontSize=10, name='text_PS',
leftIndent=20, firstLineIndent=-20, spaceBefore=5, leading=16)
# Storing the styles into a class attribute so that we can call them later on
self.styleSheet = getSampleStyleSheet()
for style in [ps1, ps2, ps3]:
self.styleSheet.add(style)
# Generate the front page
self.doFrontPage()
# Initialize the TOC
toc = TableOfContents(dotsMinLevel=0)
toc.levelStyles = [self.styleSheet['header_PS']]
# Add the TOC
self.elements.append(toc)
self.elements.append(PageBreak())
for n in range(2):
self.doOtherPage(n)
# Build the document
self.multiBuild(self.elements)
def afterFlowable(self, flowable):
"Registers TOC entries."
if flowable.__class__.__name__ == 'Paragraph':
text = flowable.getPlainText()
style = flowable.style.name
if style == 'header_PS':
self.notify('TOCEntry', (0, text, self.page))
def doFootings(self, canvas, doc):
# Create the footer
x = A4[0]-128
y = 40
canvas.saveState()
txtFooting = "Page {}".format(int(canvas._pageNumber))
canvas.drawString(x, y, txtFooting)
canvas.restoreState()
def doFootingsFrontPage(self, canvas, doc):
# Create the footer
x = 50
y = 40
canvas.saveState()
txtFooting = "I am the front page - I dont want to have a page number"
canvas.drawString(x, y, txtFooting)
canvas.restoreState()
def doFrontPage(self):
txt = 'This is the front page'
self.elements.append(Paragraph(txt, self.styleSheet['frontPage_PS']))
self.elements.append(NextPageTemplate("other_pages"))
self.elements.append(PageBreak())
def doOtherPage(self, n):
txt = 'Header {:.0f}'.format(n+1)
self.elements.append(Paragraph(txt, self.styleSheet['header_PS']))
txt ='Who stole my page number? I should be Page {:.0f}'.format(n+1)
for ii in range(10):
self.elements.append(Paragraph(txt, self.styleSheet['text_PS']))
self.elements.append(PageBreak())
if __name__ == '__main__':
fname = os.path.abspath(os.path.join('.', 'example_reportlab.pdf'))
Report = Example(fname)
In this example a PDF with 4 pages is generated, the front page, the table of content and two filling sections for the example. What I would like to obtain is to have the page numbering starting at the first section of the document (which is currently the page 3) and have it reflected into the Table of Content (i.e., Header 1 would be at page 1, Header 2 page 2 …). Or even better, be able to index the first pages i, ii, iii … then switch to a new numbering scheme 1, 2, 3 … when a certain part of the document is reached.
To my understanding it should be possible to do it; I found this example which states:
In real world documents there is another complication. You might have a fancy cover or front matter, and the logical page number 1 used in printing might not actually be page 1. Likewise, you might be doing a batch of customer docs in one RML job. So, in this case we have a more involved expression, and use the evalString tag to work out the number we want. In this example we did this by creating a name for the first page after the cover,
-+1
…
This says ‘work out the page number of the cover, add 1 and store that in the variable “page1” for future use’
But I haven’t been able to make anything out of it. I also had a look at the tests implemented by the library (test_platypus_toc.py for an example) but haven’t found anything relevant to my question.
I am using Python 3.12.9
, and reportlab 3.6.13
.