使用目录创建多个文档时,Reportlab 不会重置序列 [英] Reportlab does not reset sequences when creating multiple documents with table of contents
问题描述
我正在使用一个模板函数,该函数使用 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.
问题是我使用了同名的全局序列.h1
、h2
和 h3
出现在每个文档中.当新文档启动时,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屋!