python reportlab 生成pdf文件

# -*- coding: utf-8 -*-
# @File  : 
# @Author: ennis
# @Date  : 2019-09-16
# @Desc  : 
import os
import logging
import datetime
from utils import fileutil
from reportlab.lib import colors
from reportlab.lib.units import inch, cm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.pagesizes import letter, landscape
from reportlab.lib.utils import simpleSplit
from reportlab.pdfbase.pdfmetrics import stringWidth
from reportlab.platypus import Paragraph, Frame, PageTemplate
from reportlab.platypus import Paragraph, SimpleDocTemplate, Table, TableStyle, BaseDocTemplate, Image, PageBreak
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.fonts import addMapping
from PyPDF2 import PdfFileMerger

class SecondPagePdf(object):
    def __init__(self, pdf_name):
        self.data = [['' for col in range(107)] for row in range(60)]
        pdfmetrics.registerFont(TTFont('simsun', './resource/simsun.ttc'))
        pdfmetrics.registerFont(TTFont('simhei', './resource/simhei.ttf'))

        addMapping('cjk', 0, 0, 'simsun')  # normal
        addMapping('cjk', 1, 0, 'simhei')  # bold
        self.pdf_name = pdf_name
        self.style = getSampleStyleSheet()
        self.style.add(ParagraphStyle(fontName='simsun', name='title_', leading=15, fontSize=14, alignment=1))  # 自己增加新注册的字体
        self.style.add(ParagraphStyle(fontName='simsun', name='content', leading=7, fontSize=9))
        self.style.add(ParagraphStyle(fontName='simsun', name='content1', leading=8, fontSize=8))

    def shrink_font_size(self, aW, aH, text, style):
        """Shrinks font size by using pdfmetrics to calculate the height
        of a paragraph, given the font name, size, and available width."""

        def break_lines(text, aW):
            # simpleSplit calculates how reportlab will break up the lines for
            # display in a paragraph, by using width/fontsize.
            return simpleSplit(text, style.fontName, style.fontSize, aW)

        def line_wrap(lines, style):
            # Get overall width of text by getting stringWidth of longest line
            width = stringWidth(max(lines), style.fontName, style.fontSize)
            # Paragraph height can be calculated via line spacing and number of lines.
            height = style.leading * len(lines)
            return width, height

        lines = break_lines(text, aW)
        width, height = line_wrap(lines, style)

        while height > aH or width > aW:
            style.fontSize -= 1
            lines = break_lines(text, aW)
            width, height = line_wrap(lines, style)

    def draw_task_pdf(self):
        """
        绘制任务书pdf
        :return:
        """
        data = self.get_pdf_data()
        table_style = self.get_pdf_style()
        table1 = Table(data, colWidths=110 * [0.254 * cm], rowHeights=60 * [0.32 * cm], style=table_style)
        # table1 = Table(data, colWidths=107 * [0.254 * cm], rowHeights=54 * [0.42 * cm], style=table_style)
        story = [table1, PageBreak()]
        if not os.path.exists('./tmp'):
            os.mkdir('./tmp')
        pdf = SimpleDocTemplate(self.pdf_name, pagesize=landscape(letter), topMargin=0.3 * cm,
                                bottomMargin=0.3 * cm)
        pdf.multiBuild(story)
        
        # 合并pdf第二页
        pdfs = [file_name + '.pdf', 'second.pdf']
        merger = PdfFileMerger()
        tmp_flie = []
        for pdf in pdfs:
            f = open(pdf, 'rb')
            merger.append(f)
            tmp_flie.append(f)
        with open(file_name + '_.pdf', 'wb') as fout:
            merger.write(fout)
        for f in tmp_flie:
            f.close()
        merger.close()
        return file_name + '_.pdf'

    def set_pdf_content(self, content):
           style = ParagraphStyle(fontName='simsun', name='content2', leading=6, fontSize=7)
            self.shrink_font_size(85 * 0.254 * cm, 2 * 0.32 * cm, content["DEFECT_REPORT"], style)
            self.data[17][25] = Paragraph(content["DEFECT_REPORT"], style)
        for one_content in content:
            index = content.index(one_content)
            self.data[14 + index * 2][4] = one_content["NOMENCL"]
            self.data[14 + index * 2][34] = one_content["PART_NO"]
            self.data[14 + index * 2][62] = one_content["IPC"]
            self.data[14 + index * 2][92] = one_content["QUANTITY"]

    def get_pdf_data(self):
        """
        填充任务书数据
        :return: 返回时[45][55]二维列表
        """
        data = self.data
        I = Image('./resource/logo.png')
        I.drawHeight = 3.25 * cm * I.drawHeight / I.drawWidth
        I.drawWidth = 3.25 * cm
        data[7][3] = I
        data[7][90] = "JL-CX-WX-144-P/E"
        # data[8][4] = "TEST FORM"
        data[8][4] = Paragraph('''<para align=center leading=10><b>TEST TOOLS</b></para> ''',
                               self.style["title_"])
        data[11][4] = Paragraph('''<para align=center leading=10><b>名称<br/>Des</b></para> ''', self.style["content"])
        data[11][34] = Paragraph('''<para align=center leading=10><b>件号<br/>Part NO</b></para> ''', self.style["content"])
        data[11][62] = Paragraph('''<para align=center leading=10><b>章节<br/>AIPC</b></para> ''', self.style["content"])
        data[11][92] = Paragraph('''<para align=center leading=10><b>数量<br/>Quantity</b></para> ''', self.style["content"])
        data[58][4] = Paragraph('''<para align=left><b>底部部分</b></para> ''', self.style["content1"])
        return data

    def get_pdf_style(self):
        style = [
            ('FONTNAME', (4, 8), (102, 59), 'simsun'),
            # 第一栏
            ('SPAN', (4, 8), (102, 10)),
            ('ALIGN', (4, 8), (102, 10), 'CENTER'),  # 对齐
            ('VALIGN', (4, 8), (102, 10), 'MIDDLE'),
            ('TOPPADDING', (4, 8), (102, 10), 1),
            ('BOX', (4, 8), (102, 10), 2, colors.black),

            ('SPAN', (4, 11), (33, 13)),
            ('SPAN', (34, 11), (61, 13)),
            ('SPAN', (62, 11), (91, 13)),
            ('SPAN', (92, 11), (102, 13)),

            ('FONTSIZE', (4, 14), (102, 57), 8),
            ('ALIGN', (4, 14), (102, 57), 'CENTER'),  # 对齐
            ('BOX', (4, 11), (102, 57), 2, colors.black),
            ('VALIGN', (4, 14), (102, 57), 'MIDDLE'),
            ('GRID', (4, 11), (102, 57), 0.5, colors.black),
            # 分发
            ('SPAN', (4, 58), (43, 59)),

        ]
        for i in range(14, 58, 2):
            style.append(('SPAN', (4, i), (33, i + 1)),)
            style.append(('SPAN', (34, i), (61, i + 1)), )
            style.append(('SPAN', (62, i), (91, i + 1)), )
            style.append(('SPAN', (92, i), (102, i + 1)), )
        return style

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值