编写PDF时添加页码

时间:2019-09-09 09:59:03

标签: python python-3.x

我正在尝试自动化构建包含熊猫数据框的PDF的过程。但是,我想在页面的右下角添加页码。我还想知道我是否可以改进现有代码。

到目前为止,我已经编写了一个脚本,该脚本使用两个熊猫数据帧,将它们放在单独的pdf中,然后将它们合并在一起以创建最终的pdf。


    from reportlab.pdfgen import canvas
    from reportlab.platypus import SimpleDocTemplate
    from reportlab.pdfgen import canvas
    from reportlab.platypus import *
    from reportlab.lib import colors
    from reportlab.lib.pagesizes import letter
    import pandas as pd
    import io
    import numpy as np
    from reportlab.lib import colors
    from reportlab.lib.pagesizes import letter, inch
    from reportlab.platypus import SimpleDocTemplate, Table, TableStyle

    data = pd.read_csv('data1.csv').dropna()

    colwidths = 50

    GRID_STYLE = TableStyle(
                [('GRID', (0, 0), (-1, -1), 0.25, colors.black),
                ('ALIGN', (1, 0), (-1, -1), 'RIGHT')])


    t1 = Table(np.array(data).tolist());

    doc = SimpleDocTemplate("report1.pdf", pagesize=letter)

    element = []

    t1.setStyle(TableStyle([('ALIGN',(1,1),(-2,-2),'RIGHT'),
                           ('TEXTCOLOR',(1,1),(-2,-2),colors.black),
                           ('VALIGN',(0,0),(0,-1),'TOP'),
                           ('TEXTCOLOR',(0,0),(0,-1),colors.black),
                           #('ALIGN',(0,-1),(-1,-1),'CENTER'),
                           #('VALIGN',(0,-1),(-1,-1),'MIDDLE'),
                           ('TEXTCOLOR',(0,-1),(-1,-1),colors.black),
                           ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                           ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                           ]))

    element.append(t1)
    doc.build(element)


    data2 = pd.read_csv('data2.csv')
    t2 = Table(np.array(data2).tolist());

    doc = SimpleDocTemplate("report2.pdf", pagesize=letter)

    element2 = []

    t2.setStyle(TableStyle([('ALIGN',(1,1),(-2,-2),'RIGHT'),
                           ('TEXTCOLOR',(1,1),(-2,-2),colors.black),
                           ('VALIGN',(0,0),(0,-1),'TOP'),
                           ('TEXTCOLOR',(0,0),(0,-1),colors.black),
                           #('ALIGN',(0,-1),(-1,-1),'CENTER'),
                           #('VALIGN',(0,-1),(-1,-1),'MIDDLE'),
                           ('TEXTCOLOR',(0,-1),(-1,-1),colors.black),
                           ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                           ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                           ]))


    element.append(t2)
    doc.build(element)

    from PyPDF2 import PdfFileMerger, PdfFileReader
    pdfs = ['report1.pdf', 'report2.pdf']
    merger = PdfFileMerger()

    for file in pdfs:
        merger.append(file)

    pdf = merger.write('result.pdf')

    for page in range(pdf.getNumPages()):
        pdf_page = pdf.getPage(page)
        pdf_page.mergepage(watermark_page)

    merger.addBookmark(pagenum)
    merger.close()

我目前没有任何错误消息。我希望每页有一张表,并且有一个脚本能够创建PDF文件,该PDF的页数与我收到的表一样多,此数字可能会有所不同。所有页面都必须在页面的右下角具有页码。

我已经看到尝试使用水印进行此操作的方法,但是我不理解它,因此不确定在这里是否有用。

1 个答案:

答案 0 :(得分:0)

此答案完全受此博客帖子-http://www.blog.pythonlibrary.org/2013/08/12/reportlab-how-to-add-page-numbers/

的启发

我不完全了解这些内部函数的工作原理,但是基本思想是修改canvas.Canvas的一些内部函数,以便将页码自动添加到生成的每个页面中。

首先,创建canvas.Canvas类的子类来修改内部函数,如下所示,

from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
from reportlab.platypus import PageBreak, SimpleDocTemplate, Table, TableStyle

import numpy as np
import pandas as pd


# Custom Canvas class for automatically adding page-numbers
class MyCanvas(canvas.Canvas):
    def __init__(self, *args, **kwargs):
        canvas.Canvas.__init__(self, *args, **kwargs)
        self.pages = []

    def showPage(self):
        self.pages.append(dict(self.__dict__))
        self._startPage()

    def draw_page_number(self, page_count):
        # Modify the content and styles according to the requirement
        page = "{curr_page} of {total_pages}".format(curr_page=self._pageNumber, total_pages=page_count)
        self.setFont("Helvetica", 10)
        self.drawRightString(195*mm, 272*mm, page)

    def save(self):
        # Modify the save() function to add page-number before saving every page
        page_count = len(self.pages)
        for page in self.pages:
            self.__dict__.update(page)
            self.draw_page_number(page_count)
            canvas.Canvas.showPage(self)

        canvas.Canvas.save(self)

现在生成PDF。就您而言,

TABLE_STYLE = TableStyle([('ALIGN',(1,1),(-2,-2),'RIGHT'),
                          ('TEXTCOLOR',(1,1),(-2,-2),colors.black),
                          ('VALIGN',(0,0),(0,-1),'TOP'),
                          ('TEXTCOLOR',(0,0),(0,-1),colors.black),
                          ('TEXTCOLOR',(0,-1),(-1,-1),colors.black),
                          ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                          ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                        ])

content = list()

# This should be refactored into a for-loop
data_one = pd.read_csv('data1.csv').dropna()
t1 = Table(np.array(data_one).tolist())
t1.setStyle(TABLE_STYLE)
content.append(t1)
content.append(PageBreak())

data_two = pd.read_csv('data2.csv').dropna()
t2 = Table(np.array(data_two).tolist())
t2.setStyle(TABLE_STYLE)
content.append(t2)
content.append(PageBreak())

# Now generate the PDF at once with page numbers
doc = SimpleDocTemplate("result.pdf", pagesize=letter)
doc.build(content, canvasmaker=MyCanvas)

我已经通过生成一个虚拟PDF进行了测试,并且效果很好。希望这会有所帮助。