Skip to content

Page number incorrect when using TableOfContents.render_toc #1343

@mschoettle

Description

@mschoettle

This is a follow-up to #136.

When using the new TableOfContents.render_toc and the table of contents spans more than one page, the page numbers are incorrect.

Another issue (when using page labels) is that doing "Page x of y" (via {nb}) is not possible because the last page number can then be incorrect. And when using roman numerals for the front matter it shows the total pages.

Error details

When running the below MRE, the following issues occur:

  • page 2 (ToC) has an incorrect page number (57)
  • all content pages are shifted by one, i.e., section 1 has page 2 instead of 3

Minimal code
Please include some minimal Python code reproducing your issue:

from fpdf import FPDF
from fpdf.outline import TableOfContents

NUMBER_SECTIONS = 56


def p(pdf, text, **kwargs):
    pdf.multi_cell(
        w=pdf.epw,
        h=pdf.font_size,
        text=text,
        new_x="LMARGIN",
        new_y="NEXT",
        **kwargs,
    )


class CustomFPDF(FPDF):
    def footer(self) -> None:
        self.set_y(-15)
        self.set_font("Helvetica", size=8)
        self.cell(w=0, h=10, text="Page %s" % self.page_no(), align="C")
        self.set_font("Helvetica", size=12)


pdf = CustomFPDF()
pdf.set_font("Helvetica", size=12)
pdf.add_page()
pdf.start_section("Test", level=0)
pdf.insert_toc_placeholder(TableOfContents().render_toc, allow_extra_pages=True)

text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."

for i in range(1, NUMBER_SECTIONS):
    if i > 1:
        pdf.add_page()
    pdf.start_section(f"Section {i}", level=1)
    p(pdf, f"Section {i}")
    p(pdf, text)

pdf.output('output.pdf')

MRE 2

When using set_page_label and get_page_label it is somewhat better:

from fpdf import FPDF
from fpdf.outline import TableOfContents

NUMBER_SECTIONS = 56


def p(pdf, text, **kwargs):
    pdf.multi_cell(
        w=pdf.epw,
        h=pdf.font_size,
        text=text,
        new_x="LMARGIN",
        new_y="NEXT",
        **kwargs,
    )


class CustomFPDF(FPDF):
    def footer(self) -> None:
        self.set_y(-15)
        self.set_font("Helvetica", size=8)
        self.cell(w=0, h=10, text="Page %s" % self.get_page_label(), align="C")
        self.set_font("Helvetica", size=12)


pdf = CustomFPDF()
pdf.set_font("Helvetica", size=12)
pdf.add_page()
pdf.set_page_label(label_style="D")
pdf.start_section("Test", level=0)
pdf.insert_toc_placeholder(TableOfContents().render_toc, allow_extra_pages=True)

text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."

for i in range(1, NUMBER_SECTIONS):
    if i > 1:
        pdf.add_page()
    pdf.start_section(f"Section {i}", level=1)
    p(pdf, f"Section {i}")
    p(pdf, text)

pdf.output('output.pdf')

Issues:

  • all content pages are shifted by 1 (section 1 has page 2 instead of 3)

MRE 3

Making use of roman numerals before the actual content works with the exception of adding the total page count:

from fpdf import FPDF
from fpdf.outline import TableOfContents

NUMBER_SECTIONS = 56


def p(pdf, text, **kwargs):
    pdf.multi_cell(
        w=pdf.epw,
        h=pdf.font_size,
        text=text,
        new_x="LMARGIN",
        new_y="NEXT",
        **kwargs,
    )


class CustomFPDF(FPDF):
    def footer(self) -> None:
        self.set_y(-15)
        self.set_font("Helvetica", size=8)
        self.cell(w=0, h=10, text="Page %s of {nb}" % self.get_page_label(), align="C")
        self.set_font("Helvetica", size=12)


pdf = CustomFPDF()
pdf.set_font("Helvetica", size=12)
pdf.add_page()
pdf.set_page_label(label_style="R")
pdf.start_section("Test", level=0)
pdf.insert_toc_placeholder(TableOfContents().render_toc, allow_extra_pages=True)

text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."

pdf.set_page_label(label_style="D")

for i in range(1, NUMBER_SECTIONS):
    if i > 1:
        pdf.add_page()
    pdf.start_section(f"Section {i}", level=1)
    p(pdf, f"Section {i}")
    p(pdf, text)

pdf.output('output.pdf')

Environment
Please provide the following information:

  • Operating System: Windows, Mac OSX, Linux flavour...
  • Python version: 3.11.x
  • fpdf2 version used: 2.8.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions