python --生成pdf/插入图片;reportlab/fitz

bash 复制代码
PyMuPDF==1.22.5
reportlab==4.2.2

直接插入图片

python 复制代码
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from PIL import Image

# 创建一个 PDF 文档
c = canvas.Canvas("1.pdf", pagesize=letter)
page_width, page_height = letter

# 图片路径
image_path = r"C:\Users\Yi\Desktop\88.jpg"
image = Image.open(image_path)
img_width, img_height = image.size
img_width, img_height = img_width * 0.1, img_height * 0.1
image.close()


# 设置图片的位置(从左上角计算)
x = 0  # x 坐标
y = 0  # y 坐标(从左上角计算)
c.drawImage(image_path, x, page_height - y - img_height, width=img_width, height=img_height)

# 保存 PDF 文档
c.save()

创建pdf与插入图片

python 复制代码
import fitz  # PyMuPDF
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics

class CreateBaoXiuDan(object):
    '''生成保修单'''

    def __init__(self, pdf_name):
        pdfmetrics.registerFont(TTFont('SimHei', 'SimHei.ttf'))  # 注册中文字体
        self.pdf = SimpleDocTemplate(pdf_name, pagesize=letter)

    def table1(self, data: list):
        '''顶部表格  ■  □'''
        data = [
            ['客户姓名', '', '客户电话', '', '客户电话', ''],
            ['安装地址', '', '', '', '购买场所', ''],
            ['供暖方式', '□集中 ■独立', '管路连接方式', '□串联 ■并联 □混联', '', ''],
            ['墙体情况', '□混凝土 ■砖墙\n□石膏板 □其他', '进回水管材质', '□铝塑 □镀锌 □PPR\n□PB  □PERT  □其他', '', ''],
            ['工作类型', '□安装    □换线   □改造', '', '', '', ''],
        ]

        style = TableStyle([          # 定义表格样式
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 水平居中对齐
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 垂直居中对齐
            ('FONT', (0, 0), (-1, -1), 'SimHei'),  # 字体
            ('BACKGROUND', (0, 0), (-1, 0), '#FFFFFF'),  # 单元格背景色
            ('GRID', (0, 0), (-1, -1), 1, 'black'),  # 加网格线 0,0开始 (-1, -1) 表示到最后一个单元格(负值表示最后的单元格) 1线条宽度
            ('SPAN', (1, 1), (3, 1)),  # 合并第二行的第2、3、4列 (起始列, 起始行), (结束列, 结束行))
            ('SPAN', (3, 2), (5, 2)),
            ('SPAN', (3, 3), (5, 3)),
            ('SPAN', (1, 4), (5, 4)),
        ])
        table = Table(data, colWidths=[80, 80, 80, 80, 80, 80])  # 创建表格  元素为列的数量
        table.setStyle(style)
        return table

    def table2(self, content: list):
        '''表格2'''
        data = [
            ['订货清单', ],
            ['房间', '型号', '组数']
        ]
        data.extend(content)
        style = TableStyle([  # 定义表格样式
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 水平居中对齐
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 垂直居中对齐
            ('FONT', (0, 0), (-1, -1), 'SimHei'),  # 字体
            ('BACKGROUND', (0, 0), (-1, 0), '#FFFFFF'),  # 单元格背景色
            ('GRID', (0, 0), (-1, -1), 1, 'black'),  # 加网格线 0,0开始 (-1, -1) 表示到最后一个单元格(负值表示最后的单元格) 1线条宽度
            ('SPAN', (0, 0), (2, 0)),
        ])
        table = Table(data, colWidths=[160, 160, 160])  # 创建表格  元素为列的数量
        table.setStyle(style)
        return table

    def table3(self, content: list):
        '''表格3'''
        data = [
            ['改管材料清单', ],
            ['项目', '单价', '数量', '合计']
        ]
        data.extend(content)
        dj, sl, hj = [],[],[]
        for i in content:
            dj.append(float(i[1]))
            sl.append(int(i[2]))
            hj.append(float(i[3]))

        data.append(['总计', f'{sum(dj):.2f}', sum(sl), f'{sum(hj):.2f}'])
        style = TableStyle([  # 定义表格样式
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 水平居中对齐
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 垂直居中对齐
            ('FONT', (0, 0), (-1, -1), 'SimHei'),  # 字体
            ('BACKGROUND', (0, 0), (-1, 0), '#FFFFFF'),  # 单元格背景色
            ('GRID', (0, 0), (-1, -1), 1, 'black'),  # 加网格线 0,0开始 (-1, -1) 表示到最后一个单元格(负值表示最后的单元格) 1线条宽度
            ('SPAN', (0, 0), (3, 0)),
        ])
        table = Table(data, colWidths=[120, 120, 120, 120])  # 创建表格  元素为列的数量
        table.setStyle(style)
        return table

    def table4(self):
        '''表格4'''
        data = [
            ['完工状态', ],
            ['压力测试', '□已做       □未做'],
            ['阀门状态', '□关闭       □开启'],
            ['放气螺栓', '□已拧紧      □未拧紧'],
            ['所有接口', '□无漏水      □漏水'],
            ['位置正确', '□是         □否'],
            ['清理现场', '□是         □否']
        ]

        style = TableStyle([  # 定义表格样式
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 水平居中对齐
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 垂直居中对齐
            ('FONT', (0, 0), (-1, -1), 'SimHei'),  # 字体
            ('BACKGROUND', (0, 0), (-1, 0), '#FFFFFF'),  # 单元格背景色
            ('GRID', (0, 0), (-1, -1), 1, 'black'),  # 加网格线 0,0开始 (-1, -1) 表示到最后一个单元格(负值表示最后的单元格) 1线条宽度
            ('SPAN', (0, 0), (1, 0)),
        ])
        table = Table(data, colWidths=[240, 240])  # 创建表格  元素为列的数量
        table.setStyle(style)
        return table

    def table5(self):
        '''表格5'''
        data = [
            ['\n用户意见\n', ''],
        ]

        style = TableStyle([  # 定义表格样式
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),  # 水平居中对齐
            ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),  # 垂直居中对齐
            ('FONT', (0, 0), (-1, -1), 'SimHei'),  # 字体
            ('BACKGROUND', (0, 0), (-1, 0), '#FFFFFF'),  # 单元格背景色
            ('GRID', (0, 0), (-1, -1), 1, 'black'),  # 加网格线 0,0开始 (-1, -1) 表示到最后一个单元格(负值表示最后的单元格) 1线条宽度
        ])
        table = Table(data, colWidths=[80, 400])  # 创建表格  元素为列的数量
        table.setStyle(style)
        return table


    def qianzi(self):
        '''签字区'''
        text_style = ParagraphStyle(
            name='TitleStyle',
            fontName='SimHei',
            fontSize=10,
            alignment=0,
            # spaceAfter=5,
            fontWeight='Bold'  # 设置加粗
        )
        nbsp = ' '
        text = [
            Paragraph('签字区: (签字前请阅读背后合同说明,未签字或未付安装费用本协议不生效)', text_style),
            Paragraph(f'改造网点:{nbsp * 35}安装网点:', text_style),
            Paragraph(f'改造时间:{nbsp * 35}安装网点24小时电话:', text_style),
            Paragraph(f'用户签字:{nbsp * 35}施工人员签字:', text_style),
        ]
        return text

    def insert_img(self, img_path: str, input_pdf: str, output_pdf: str):
        '''插入图片'''
        pdf_document = fitz.open(input_pdf)
        page = pdf_document[0]   # 选择要插入图片的页面(这里选择第一页)
        image_rect = fitz.Rect(10, 90, 30, 1110)  # 左上角x,y  和右下角的x,y
        page.insert_image(image_rect, filename=img_path)  # 在页面上插入图片
        pdf_document.save(output_pdf)   # 保存修改后的 PDF 文件
        pdf_document.close()


    def save(self, title):
        '''保存'''
        title_style = ParagraphStyle(
            name='TitleStyle',
            fontName='SimHei',
            fontSize=16,
            alignment=1,
            spaceAfter=12,
            fontWeight='Bold'  # 设置加粗
        )
        title = Paragraph(title, title_style)
        elements = [title,
                    self.table1([]),
                    self.table2([('11', '22', '33'), ('we', 're', 'gf')]),
                    self.table3([('1', '1', '1', '1'), ('2', '2', '2', '2')]),
                    self.table4(),
                    self.table5()
                    ]
        elements.extend(self.qianzi())
        self.pdf.build(elements)



if __name__ == '__main__':
    a = CreateBaoXiuDan('1.pdf')
    a.save('散热器安装保修协议')
    a.insert_img(r'C:\Users\Yi\Desktop\88.png', r'D:\code\nuantong\backstage\1.pdf', r'D:\code\nuantong\backstage\2.pdf')
相关推荐
LyaJpunov12 分钟前
C++中move和forword的区别
开发语言·c++
程序猿练习生17 分钟前
C++速通LeetCode中等第9题-合并区间
开发语言·c++·leetcode
一名路过的小码农27 分钟前
C/C++动态库函数导出 windows
c语言·开发语言·c++
m0_6312704029 分钟前
标准c语言(一)
c语言·开发语言·算法
万河归海42829 分钟前
C语言——二分法搜索数组中特定元素并返回下标
c语言·开发语言·数据结构·经验分享·笔记·算法·visualstudio
Messiah___35 分钟前
【论文阅读】Slim Fly: A Cost Effective Low-Diameter Network Topology 一种经济高效的小直径网络拓扑
开发语言·php
农民小飞侠1 小时前
python AutoGen接入开源模型xLAM-7b-fc-r,测试function calling的功能
开发语言·python
指尖流烟1 小时前
C#调用图表的使用方法
开发语言·c#
战神刘玉栋1 小时前
《程序猿之设计模式实战 · 观察者模式》
python·观察者模式·设计模式
敲代码不忘补水1 小时前
Python 项目实践:简单的计算器
开发语言·python·json·项目实践