Оглавление Python ReportLab Проблема с нумерацией страницPython

Программы на Python
Ответить
Anonymous
 Оглавление Python ReportLab Проблема с нумерацией страниц

Сообщение Anonymous »

Мне нужно создать PDF-файл с оглавлением в Python (v3.10) с помощью reportlab (v3.6.10) (SimpleDocTemplate). Номера страниц должны задаваться динамически, но примеры, которые мне удалось найти, не позволяют этого. Вот что у меня есть на данный момент.
(Оглавлению нужны гиперссылки для перехода внутри документа - это работает и опубликовано здесь, так как я не нашел онлайн-примера)
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Paragraph, Flowable, Paragraph, PageBreak, Spacer, Table
from reportlab.platypus import PageBreak
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('', style=styles['Heading1']))
story.append(DelayedRef(toc, 0, '1. Part 1 Header', 1))
for x in range(10):
story.append(Paragraph(ipsum, style=styles['Normal']))

story.append(PageBreak())
story.append(Paragraph('', style=styles['Heading1']))
story.append(DelayedRef(toc, 0, '2. Part 2 Header', 1))
story.append(Paragraph(ipsum, style=styles['Normal']))

story.append(Paragraph('', style=styles['Heading2']))
story.append(DelayedRef(toc, 1, '2.1 Part 2.1 Header', 1))
for x in range(10):
story.append(Paragraph(ipsum, style=styles['Normal']))

story.append(PageBreak())
story.append(Paragraph('', style=styles['Heading1']))
story.append(DelayedRef(toc, 0, '3. Part 3 Header',1))

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

if __name__ == '__main__':
simple_toc()


Подробнее здесь: https://stackoverflow.com/questions/776 ... ng-problem
111
 Re: Оглавление Python ReportLab Проблема с нумерацией страниц

Сообщение 111 »

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

from reportlab.lib.utils import simpleSplit

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)

# на момент создания оглавления на второй странице номера страниц динамических разделов неизвестны, поэтому надо сначала прогнать "вхолостую" весь документ, чтобы их вычитслить
# прогон для расчета номеров страниц оглавления

pagesforTOC = []
pagenumber = 3 #первая страница для оглавления

story0 = []
styles = getSampleStyleSheet()

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

story0.append(PageBreak())
story0.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)]
story0.append(toc)

story0.append(PageBreak())
pagesforTOC.append(pagenumber)
pagenumber += 1

story0.append(Paragraph('<a name="Part1"/>1. Part 1 Header <a href="#TOC" color="blue">&#8593;</a>',
style=styles['Heading1']))
story0.append(DelayedRef(toc, 0, '<a href="#Part1" color="blue">1. Part 1 Header</a>', 1))
lines = 0
parwidth = 595.2 - 20 - 20 # ширина текста
linesnumber = 70 # ограничение на число строк на странице
currentparnum = 0
for x in range(10):
currentparnum += 1
story0.append(Paragraph(ipsum, style=styles['Normal']))
lines = lines + len(simpleSplit(ipsum, 'Times-Roman', round(10), parwidth)) # считаем число строк, 'Times-Roman', round(10) - шрифт и его размер для используемого стиля
if lines>linesnumber:
# переход на новую страницу надо задать явно
story0.append(PageBreak())
pagenumber += 1
lines = 0
currentparnum = 0
if currentparnum == 10:
story0.append(PageBreak())

pagesforTOC.append(pagenumber)
pagenumber += 1

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

story0.append(Paragraph('<a name="Part21"/>2.1 Part 2.1 Header <a href="#TOC" color="blue">&#8593;</a>',
style=styles['Heading2']))
story0.append(DelayedRef(toc, 1, '<a href="#Part21" color="blue">2.1 Part 2.1 Header</a>', 1))
lines = 0
parwidth = 595.2 - 20 - 20 # ширина текста
linesnumber = 70 # ограничение на число строк на странице
currentparnum = 0
for x in range(10):
currentparnum += 1
story0.append(Paragraph(ipsum, style=styles['Normal']))
lines = lines + len(simpleSplit(ipsum, 'Times-Roman', round(10), parwidth))
if lines>linesnumber:
story0.append(PageBreak())
pagenumber += 1
lines = 0
currentparnum = 0
if currentparnum == 10:
story0.append(PageBreak())

story0.append(PageBreak())
pagenumber += 1
pagesforTOC.append(pagenumber)

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

story0 = []

print(pagesforTOC)

# конец расчета номеров страниц

xxx = 0
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())
par = Paragraph('<a name="Part1"/>1. Part 1 Header <a href="#TOC" color="blue">&#8593;</a>', style=styles['Heading1'])
story.append(par)

story.append(DelayedRef(toc, 0, '<a href="#Part1" color="blue">1. Part 1 Header</a>', pagesforTOC[xxx]))
xxx += 1
lines = 0
parwidth = 595.2 - 20 - 20 # ширина текста
linesnumber = 70 # ограничение на число строк на странице
for x in range(10):
story.append(Paragraph(ipsum, style=styles['Normal']))
lines = lines + len(simpleSplit(ipsum, 'Times-Roman', round(10), parwidth))
if lines > linesnumber:
story.append(PageBreak())
pagenumber += 1
lines = 0

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>', pagesforTOC[xxx]))
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,0, '<a href="#Part21" color="blue">2.1 Part 2.1 Header</a>', pagesforTOC[xxx]))
xxx += 1
lines = 0
parwidth = 595.2 - 20 - 20 # ширина текста
linesnumber = 70 # ограничение на число строк на странице
for x in range(10):
story.append(Paragraph(ipsum, style=styles['Normal']))
lines = lines + len(simpleSplit(ipsum, 'Times-Roman', round(10), parwidth))
if lines > linesnumber:
story.append(PageBreak())
pagenumber += 1
lines = 0

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>', pagesforTOC[xxx]))

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

if __name__ == '__main__':
simple_toc()
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»