Below is the code. I also attached it in case the formatting in the
email gets lost.
I only want <pages x of y>. I don't care about multiple passes.
I'm new to ReportLab and PDF gen. It seems the bookmarks are tied to a
position in the document. I don't see the need to know the page numbers
when creating the TOC. You guys may be abstracting that detail away
behind the scenes.
I can tell you don't like the numbered canvas but I don't understand
what the solution is to get <page x of y>. Can you give me more details
of how to do this?
Thanks for your help!!!!
Brian
"""
reportgen with numbered canvas
"""
import sys
from reportlab.pdfgen import canvas
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import inch
from reportlab.lib.units import mm
from reportlab.platypus import SimpleDocTemplate
from reportlab.platypus.tableofcontents import TableOfContents
from reportlab.platypus import PageBreak
from reportlab.platypus import Paragraph
styles = getSampleStyleSheet()
styleN = styles['Normal']
styleH = styles['Heading1']
styleH2 = styles['Heading2']
styleTitle = styles['Title']
elements = []
class NumberedCanvas(canvas.Canvas):
"""
for adding page x of y to each page
based on:
http://code.activestate.com/recipes/576832/
modified:
skip title page
renamed draw_page_number to draw_footer since footer is more
than page number
"""
def __init__(self, *args, **kwargs):
canvas.Canvas.__init__(self, *args, **kwargs)
self._saved_page_states = []
def showPage(self):
self._saved_page_states.append(dict(self.__dict__))
self._startPage()
def save(self):
"""
add page info to each page (page x of y)
"""
num_pages = len(self._saved_page_states)
#modify so will skip the first page for adding footer
for (i, state) in enumerate(self._saved_page_states):
self.__dict__.update(state)
if i!=0:
self.draw_footer(num_pages)
canvas.Canvas.showPage(self)
canvas.Canvas.save(self)
def draw_footer(self, page_count):
"""
draws the footer on the page
originally called draw_page_number but renamed since adding
complete footer
"""
self.setFont("Helvetica", 7)
self.drawRightString(200*mm, 20*mm,
"Page %d of %d" % (self._pageNumber, page_count))
class ModifiedSimpleDocTemplate(SimpleDocTemplate):
"""
modified version of SimpleDocTemplate
"""
def afterFlowable(self, flowable):
"""
called after a flowable has been rendered
based on user manual to add TOC
Detect Level 1 and 2 headings, build outline, and track chapter title.
"""
if isinstance(flowable, Paragraph):
txt = flowable.getPlainText()
#had to add style
style =
flowable.style.name
if style=='Heading1':
#make h1 clickable
key = 'h1-%s'%self.seq.nextf('heading1')
#logger.debug( 'heading 1: txt=%s and key = %s and
page=%s'%(txt, key,
self.page))
self.canv.bookmarkPage(key)
self.notify('TOCEntry', (0, txt,
self.page, key))
elif style=='Heading2':
key = 'h2-%s'%self.seq.nextf('heading2')
self.canv.bookmarkPage(key)
self.notify('TOCEntry', (1, txt,
self.page, key))
doc = ModifiedSimpleDocTemplate('testing.pdf')
#TOC
if True:
elements.append( Paragraph('Table of Contents',styleH) )
toc = TableOfContents()
PS = ParagraphStyle
toc.levelStyles = [
PS(fontName='Times-Bold', fontSize=14,
name='TOCHeading1',
leftIndent=20, firstLineIndent=-20,
spaceBefore=5, leading=16),
PS(fontSize=12, name='TOCHeading2',
leftIndent=40, firstLineIndent=-20,
spaceBefore=0, leading=12),
PS(fontSize=10, name='TOCHeading3',
leftIndent=60, firstLineIndent=-20,
spaceBefore=0, leading=12),
PS(fontSize=10, name='TOCHeading4',
leftIndent=100, firstLineIndent=-20,
spaceBefore=0, leading=12),
]
elements.append(toc)
elements.append( PageBreak() )
#generate filler elements
if True:
for i in range(100):
#p = Paragraph("This is a Heading %s"%i,styleH)
p = Paragraph("This is a Heading %s"%i,styleH2)
elements.append( p )
doc.multiBuild( elements, canvasmaker=NumberedCanvas)
#canvasmaker=NumberedCanvas canvasmaker=canvas.Canvas