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')