You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python ReportLab生成PDF目录时动态设置页码的问题

Python 3.10 + ReportLab 3.6.10 生成带动态页码与跳转目录的PDF实现

需求:使用Python 3.10结合ReportLab 3.6.10的SimpleDocTemplate生成包含目录的PDF,要求页码支持动态设置,现有示例大多不具备该功能。以下是已完成的实现代码,目录已支持文档内跳转超链接:

from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Paragraph, Flowable, PageBreak, Spacer, Table
from reportlab.platypus.tableofcontents import TableOfContents
from reportlab.lib.units import inch

class DelayedRef(Flowable):
    _ZEROSIZE = True

    def __init__(self, toc, *args):
        self.args = args
        self.toc = toc

    def wrap(self,w,h):
        return 0,0

    def draw(self,*args,**kwd):
        self.toc.addEntry(*self.args)

def addPageNumber(canvas, doc):
    """
    Add the page number
    """
    page_num = canvas.getPageNumber()
    text = "- %s -" % page_num
    canvas.drawRightString(4.5*inch,0.5*inch, text)

def simple_toc():
    docFile = 'test.pdf'
    print(docFile)

    ipsum = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
    sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
    nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
    reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
    pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
    culpa qui officia deserunt mollit anim id est laborum.'''

    doc = SimpleDocTemplate(docFile)
    story = []
    styles = getSampleStyleSheet()

    story.append(Paragraph("The Title", style=styles['Heading1']))
    story.append(Paragraph("Notes:", style=styles['Normal']))
    story.append(Paragraph(ipsum, style=styles['Normal']))

    story.append(PageBreak())
    story.append(Paragraph('<a name="TOC"/>Table of Contents', style=styles['Heading1']))
    toc = TableOfContents()
    toc.levelStyles = [ParagraphStyle(fontName='Helvetica', fontSize=14, name='Heading1',leftIndent=20, firstLineIndent=-20, spaceBefore=5,leading=16),
                      ParagraphStyle(fontName='Times-Roman', fontSize=14, name='Heading2',leftIndent=20, firstLineIndent=-20, spaceBefore=5,leading=16)]
    story.append(toc)

    story.append(PageBreak())
    story.append(Paragraph('<a name="Part1"/>1. Part 1 Header <a href="#TOC" color="blue">&#8593;</a>', style=styles['Heading1']))
    story.append(DelayedRef(toc, 0, '<a href="#Part1" color="blue">1. Part 1 Header</a>', 1))
    for x in range(10):
        story.append(Paragraph(ipsum, style=styles['Normal']))

    story.append(PageBreak())
    story.append(Paragraph('<a name="Part2"/>2. Part 2 Header <a href="#TOC" color="blue">&#8593;</a>', style=styles['Heading1']))
    story.append(DelayedRef(toc, 0, '<a href="#Part2" color="blue">2. Part 2 Header</a>', 1))
    story.append(Paragraph(ipsum, style=styles['Normal']))


    story.append(Paragraph('<a name="Part21"/>2.1 Part 2.1 Header <a href="#TOC" color="blue">&#8593;</a>', style=styles['Heading2']))
    story.append(DelayedRef(toc, 1, '<a href="#Part21" color="blue">2.1 Part 2.1 Header</a>', 1))
    for x in range(10):
        story.append(Paragraph(ipsum, style=styles['Normal']))

    story.append(PageBreak())
    story.append(Paragraph('<a name="Part3"/>3. Part 3 Header <a href="#TOC" color="blue">&#8593;</a>', style=styles['Heading1']))
    story.append(DelayedRef(toc, 0, '<a href="#Part3" color="blue">3. Part 3 Header</a>',1))

    doc.multiBuild(story, onFirstPage=addPageNumber, onLaterPages=addPageNumber)

if __name__ == '__main__':
    simple_toc()

内容的提问来源于stack exchange,提问作者cornhenge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:57:06