使用目录创建多个文档时,Reportlab 不会重置序列 [英] Reportlab does not reset sequences when creating multiple documents with table of contents

查看:35
本文介绍了使用目录创建多个文档时,Reportlab 不会重置序列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个模板函数,该函数使用 reportlab 在一个程序执行中创建多个 PDF 文档.

I am using a template function that creates multiple PDF documents in one program execution using reportlab.

这些文档的结构相同,标题相同.它们仅在标题下方的内容上有所不同.所有这些文档都包含一个目录元素.

These documents are identical by structure and have identical headings. They only differ in content below the headings. All of these documents contain a table of contents element.

我正在使用序列标签( 等)来创建编号的标题 e.G.

I am using sequence tags (<seq/> etc.) to create numbered headings e. g.

1. Top1
  1.1 Sub1
2. Top2
  2.1 Sub1
  2.2 Sub2

这适用于单个文档,但是一旦我在第一个文档之后创建第二个文档,序列就不会重置,第二个文档的 TOC 看起来像

This works well for one single document but as soon as I create a second one right after the first the sequences are not reset and the second document's TOC looks like

2. Top1
  2.1 Sub1
3. Top2
  3.1 Sub1
  3.2 Sub2

创建第三个文档 Top1 将从 3 开始.

Creating a third document Top1 will start with 3.

但由于我正在开始一个新文档,创建一个新的 BaseDocTemplate 类,我期望序列被重置.我怎样才能做到这一点?

But since I am starting a new document, creating a new BaseDocTemplate class, I was expecting the sequences to be reset. How can I achieve that?

我尝试使用 reportlab 的其中一个教程创建一个尽可能小的示例.

I've tried to create a small as possible example using one of the tutorials for reportlab.

from  reportlab.lib.styles import ParagraphStyle as PS
from  reportlab.platypus import PageBreak
from  reportlab.platypus.paragraph import Paragraph
from  reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
from  reportlab.platypus.tableofcontents import TableOfContents
from  reportlab.platypus.frames import Frame
from  reportlab.lib.units import cm

class MyDocTemplate(BaseDocTemplate):
     def __init__(self, filename, **kw):
         self.allowSplitting = 0
         super().__init__(filename, **kw)
         template = PageTemplate('normal', [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')])
         self.addPageTemplates(template)

# Entries to the table of contents can be done either manually by
# calling the addEntry method on the TableOfContents object or automatically
# by sending a 'TOCEntry' notification in the afterFlowable method of
# the DocTemplate you are using. The data to be passed to notify is a list
# of three or four items countaining a level number, the entry text, the page
# number and an optional destination key which the entry should point to.
# This list will usually be created in a document template's method like
# afterFlowable(), making notification calls using the notify() method
# with appropriate data.

     def afterFlowable(self, flowable):
         "Registers TOC entries."
         if flowable.__class__.__name__ == 'Paragraph':
             text = flowable.getPlainText()
             style = flowable.style.name
             if style == 'Heading1':
                 self.notify('TOCEntry', (0, text, self.page))
             if style == 'Heading2':
                 self.notify('TOCEntry', (1, text, self.page))


centered = PS(name = 'centered',
    fontSize = 30,
    leading = 16,
    alignment = 1,
    spaceAfter = 20)

h1 = PS(
    name = 'Heading1',
    fontSize = 14,
    leading = 16)


h2 = PS(name = 'Heading2',
    fontSize = 12,
    leading = 14)

# Heading definition with sequence numbers
heading = {
    1 : "<seq id='h1'/>.<seqreset id='h2'/><seqreset id='h3'/> {}",
    2 : "<seq id='h1' inc='no'/>.<seq id='h2'/><seqreset id='h3'/> {}",
    3 : "<seq id='h1' inc='no'/>.<seq id='h2' inc='no'/>.<seq id='h3'/> {}",
}

def build_document(filename):
    # Build story.
    story = []

    # Create an instance of TableOfContents. Override the level styles (optional)
    # and add the object to the story

    toc = TableOfContents()
    toc.levelStyles = [
        PS(fontName='Times-Bold', fontSize=20, name='TOCHeading1', leftIndent=20, firstLineIndent=-20, spaceBefore=10, leading=16),
        PS(fontSize=18, name='TOCHeading2', leftIndent=40, firstLineIndent=-20, spaceBefore=5, leading=12),
    ]
    story.append(toc)

    story.append(Paragraph('<b>Table of contents</b>', centered))
    story.append(PageBreak())
    story.append(Paragraph(heading[1].format('First heading'), h1))
    story.append(Paragraph('Text in first heading', PS('body')))
    story.append(Paragraph(heading[2].format('First sub heading'), h2))
    story.append(Paragraph('Text in first sub heading', PS('body')))
    story.append(PageBreak())
    story.append(Paragraph(heading[2].format('Second sub heading'), h2))
    story.append(Paragraph('Text in second sub heading', PS('body')))
    story.append(PageBreak())
    story.append(Paragraph(heading[2].format('Last heading'), h1))
    doc = MyDocTemplate(filename)
    doc.multiBuild(story)

if __name__ == "__main__":
    build_document("1.pdf")
    build_document("2.pdf")

推荐答案

我找到了一个快速解决方案,可以解决我的问题,但我不喜欢将其作为最终解决方案.

I have found a quick solution which solves my problem but which I don't like as a final solution.

问题是我使用了同名的全局序列.h1h2h3 出现在每个文档中.当新文档启动时,reportlab 似乎不会重置它们.因此,我在填写故事列表之前手动重置.

The problem is that I am using global sequences with the same name. h1, h2 and h3 appear in every document. And reportlab doesn't seem to reset them when a new document is started. So instead I reset the manually before filling the story list.

def build_document(filename):
    # Build story. story = []

    # Reset the sequences
    story.append(Paragraph("<seqreset id='h1'/>", PS('body')))
    story.append(Paragraph("<seqreset id='h2'/>", PS('body')))
    story.append(Paragraph("<seqreset id='h3'/>", PS('body')))

    # ...  rest of the code from the question

这篇关于使用目录创建多个文档时,Reportlab 不会重置序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆