Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用目录创建多个文档时,Reportlab不会重置序列_Python_Python 3.x_Reportlab - Fatal编程技术网

Python 使用目录创建多个文档时,Reportlab不会重置序列

Python 使用目录创建多个文档时,Reportlab不会重置序列,python,python-3.x,reportlab,Python,Python 3.x,Reportlab,我正在使用一个模板函数,该函数使用reportlab在一个程序执行中创建多个PDF文档 这些文件的结构相同,标题也相同。它们仅在标题下的内容不同。所有这些文档都包含一个目录元素 我正在使用序列标签(等)创建编号标题e。g 1. Top1 1.1 Sub1 2. Top2 2.1 Sub1 2.2 Sub2 这对一个文档很有效,但只要我在第一个文档之后创建第二个文档,序列就不会重置,第二个文档的TOC如下所示 2. Top1 2.1 Sub1 3. Top2 3.1 Sub1

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

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

我正在使用序列标签(
等)创建编号标题e。g

1. Top1
  1.1 Sub1
2. Top2
  2.1 Sub1
  2.2 Sub2
这对一个文档很有效,但只要我在第一个文档之后创建第二个文档,序列就不会重置,第二个文档的TOC如下所示

2. Top1
  2.1 Sub1
3. Top2
  3.1 Sub1
  3.2 Sub2
创建第三个文档
Top1
将从
3
开始

但是,由于我正在启动一个新文档,创建一个新的
BaseDocTemplate
类,所以我希望序列被重置。我怎样才能做到这一点

我尝试使用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")
从reportlab.lib.styles将段落样式导入为PS
从reportlab.platypus导入PageBreak
来自reportlab.platypus.paragration导入段落
从reportlab.platypus.DoctTemplate导入页面模板,BaseDoctTemplate
从reportlab.platypus.tableofcontents导入目录
从reportlab.platypus.frames导入框架
从reportlab.lib.units导入cm
类MyDoctTemplate(BaseDoctTemplate):
def u uu init uuuu(self,文件名,**kw):
self.allowSplitting=0
super()。\uuuuu init\uuuuu(文件名,**kw)
template=PageTemplate('normal',[Frame(2.5*cm,2.5*cm,15*cm,25*cm,id='F1'))
self.addPageTemplates(模板)
#目录的条目可以通过以下方式手动完成:
#在TableOfContents对象或自动调用addEntry方法
#通过在的afterFlowable方法中发送“TOCEntry”通知
#您正在使用的DocTemplate。要传递给notify的数据是一个列表
#三个或四个项目中的一个级别编号,条目文本,页面
#数字和条目应指向的可选目标键。
#此列表通常使用文档模板的方法创建,如
#afterFlowable(),使用notify()方法进行通知调用
#有适当的数据。
def可后流式(自动、可流动):
“注册TOC条目。”
如果是可流动的。类别名称=段落:
text=flowable.getPlainText()
style=flowable.style.name
如果样式=='Heading1':
self.notify('toccentry',(0,文本,self.page))
如果样式=='Heading2':
self.notify('toccentry',(1,文本,self.page))
居中=PS(名称=‘居中’,
fontSize=30,
领先=16,
对齐=1,
spaceAfter=20)
h1=PS(
名称='Heading1',
fontSize=14,
领先=16)
h2=PS(名称='Heading2',
fontSize=12,
领先=14)
#带序列号的标题定义
标题={
1 : ". {}",
2 : ". {}",
3 : ".. {}",
}
def build_文档(文件名):
#构建故事。
故事=[]
#创建TableOfContents的实例。替代标高样式(可选)
#并将对象添加到故事中
toc=目录()
toc.levelStyles=[
PS(fontName='Times-Bold',fontSize=20,name='toheading1',leftIndent=20,firstLineIndent=-20,spaceBefore=10,leading=16),
PS(fontSize=18,name='TOCHeading2',leftIndent=40,firstLineIndent=-20,spaceBefore=5,leading=12),
]
故事附加(toc)
附加(段落(“目录”,居中))
story.append(PageBreak())
附加(段落(标题[1]。格式(“第一标题”),h1))
附加(段落('第一标题中的文本',PS('正文'))
附加(段落(标题[2]。格式(“第一副标题”),h2))
故事。附加(段落(“第一小标题中的文本”,PS(“正文”))
story.append(PageBreak())
附加(段落(标题[2]。格式(“第二副标题”),h2))
附加(段落(‘第二小标题中的文本’、PS(‘正文’))
story.append(PageBreak())
附加(段落(标题[2]。格式(“最后一个标题”),h1))
doc=MyDocTemplate(文件名)
多版本文档(故事)
如果名称=“\uuuuu main\uuuuuuuu”:
构建文档(“1.pdf”)
构建文档(“2.pdf”)

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

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

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
def build_文档(文件名):
#构建故事。故事=[]
#重置序列
故事。附加(段落(“,PS(‘正文’))
故事。附加(段落(“,PS(‘正文’))
故事。附加(段落(“,PS(‘正文’))
# ...  问题的其余代码

看起来所使用的
reportlab.lib.sequencer.sequencer
对象是全局对象

您可以通过提供新的序列器重置所有计数器

    from reportlab.lib.sequencer import setSequencer, Sequencer

    
    setSequencer(Sequencer())
您可以通过执行以下操作重置单个计数器:

    from reportlab.lib.sequencer import getSequencer

    s = getSequencer()
    s.reset('h1')
您还可以尝试直接使用Sequencer,而不是注入XML

类序列器:使段落编号变得容易的东西, 部分、图像和其他任何内容。这些功能包括注册 序列的新字符串格式,以及一些计数器的“链” 当他们的父母重新设定时。它记录了许多信息 “计数器”,根据请求创建


仅仅第一个
就足够了吗?当第一次使用
h1
时,其他已重置?@B8vrede no。这似乎不够。我已经对它进行了测试,但序列仍然是递增的。我知道可以链接序列,然后重置
h1
就足够了,但在我的示例中,它们似乎没有链接。
Usage::
 >>> seq = Sequencer()
 >>> seq.next('Bullets')
 1
 >>> seq.next('Bullets')
 2
 >>> seq.next('Bullets')
 3
 >>> seq.reset('Bullets')
 >>> seq.next('Bullets')
 1
 >>> seq.next('Figures')
 1
 >>>