1 Star 0 Fork 0

Monkey/gen_pdf

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
gen_pdf.py 11.00 KB
一键复制 编辑 原始数据 按行查看 历史
Monkey 提交于 2023-09-21 22:43 . up
from reportlab.pdfbase import pdfmetrics # 注册字体
from reportlab.pdfbase.ttfonts import TTFont # 字体类
from reportlab.platypus import Table, SimpleDocTemplate, Paragraph, Image # 报告内容相关类
from reportlab.lib.pagesizes import letter # 页面的标志尺寸(8.5*inch, 11*inch)
from reportlab.lib.styles import getSampleStyleSheet # 文本样式
from reportlab.lib import colors # 颜色模块
from reportlab.graphics.charts.barcharts import VerticalBarChart # 图表类
from reportlab.graphics.charts.legends import Legend # 图例类
from reportlab.graphics.shapes import Drawing # 绘图工具
from reportlab.lib.units import cm # 单位:cm
from reportlab.graphics.shapes import Image as DrawingImage
import csv
# 注册字体(提前准备好字体文件, 如果同一个文件需要多种字体可以注册多个)
pdfmetrics.registerFont(TTFont('SimSun', '/System/Library/Fonts/STHeiti Light.ttc'))
class Graphs:
# 绘制标题
@staticmethod
def draw_title(title, **kwargs):
# 获取所有样式表
style = getSampleStyleSheet()
# 拿到标题样式
ct = style['Heading1']
# 单独设置样式相关属性
ct.fontName = 'SimSun'
ct.fontSize = kwargs.get('font_size', 18)
ct.leading = 50
ct.textColor = kwargs.get('text_color', colors.green)
# alignment: 对齐方式, 0-左对齐, 1-居中对齐, 2-右对齐
ct.alignment = kwargs.get('alignment', 1)
ct.bold = True
# 创建标题对应的段落,并且返回
return Paragraph(title, ct)
# 绘制小标题
@staticmethod
def draw_little_title(title: str):
# 获取所有样式表
style = getSampleStyleSheet()
# 拿到标题样式
ct = style['Normal']
# 单独设置样式相关属性
ct.fontName = 'SimSun' # 字体名
ct.fontSize = 15 # 字体大小
ct.leading = 30 # 行间距
ct.textColor = colors.red # 字体颜色
# 创建标题对应的段落,并且返回
return Paragraph(title, ct)
# 绘制普通段落内容
@staticmethod
def draw_text(text: str, **kwargs):
"""
:params text: 输入的文本
:params alignment: 对齐方式, 0-左对齐, 1-居中对齐, 2-右对齐
"""
# 获取所有样式表
style = getSampleStyleSheet()
# 获取普通样式
ct = style['Normal']
ct.fontName = 'SimSun'
ct.fontSize = kwargs.get('font_size', 12)
ct.wordWrap = 'CJK' # 设置自动换行
ct.alignment = kwargs.get('alignment', 0)
ct.firstLineIndent = kwargs.get('first_line_indent', 32) # 第一行开头空格
ct.leading = 25
if kwargs.get('text_color'):
ct.textColor = kwargs.get('text_color')
if kwargs.get('leftIndent'):
ct.leftIndent = kwargs.get('left_indent')
if kwargs.get('space_before'):
ct.spaceBefore = kwargs.get('space_before')
return Paragraph(text, ct)
# 绘制表格
@staticmethod
def draw_table(*args, col_width=120):
# 列宽度
col_width = col_width
"""
(0, 0), (-1, -1) 表示修改的范围
(x, y)
"""
style = [
('FONTNAME', (0, 0), (-1, -1), 'SimSun'), # 字体
('FONTSIZE', (0, 0), (-1, 0), 12), # 第一行的字体大小
('FONTSIZE', (0, 1), (-1, -1), 10), # 第二行到最后一行的字体大小
('BACKGROUND', (0, 0), (-1, 0), '#d5dae6'), # 设置第一行背景颜色
('ALIGN', (0, 0), (-1, -1), 'CENTER'), # 第一行水平居中
('ALIGN', (0, 1), (-1, -1), 'LEFT'), # 第二行到最后一行左右左对齐
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), # 所有表格上下居中对齐
('TEXTCOLOR', (0, 0), (-1, -1), colors.darkslategray), # 设置表格内文字颜色
('GRID', (0, 0), (-1, -1), 0.5, colors.grey), # 设置表格框线为grey色,线宽为0.5
# ('SPAN', (0, 1), (0, 2)), # 合并第一列二三行
# ('SPAN', (0, 3), (0, 4)), # 合并第一列三四行
# ('SPAN', (0, 5), (0, 6)), # 合并第一列五六行
# ('SPAN', (0, 7), (0, 8)), # 合并第一列五六行
]
table = Table(args, colWidths=col_width, style=style)
return table
# 创建图表
@staticmethod
def draw_bar(bar_data: list, ax: list, items: list, value_min=0, value_max=500):
drawing = Drawing(500, 250)
bc = VerticalBarChart()
bc.x = 45 # 整个图表的x坐标
bc.y = 45 # 整个图表的y坐标
bc.height = 200 # 图表的高度
bc.width = 350 # 图表的宽度
bc.data = bar_data
bc.strokeColor = colors.black # 顶部和右边轴线的颜色
bc.valueAxis.valueMin = value_min # 设置y坐标的最小值
bc.valueAxis.valueMax = value_max # 设置y坐标的最大值
bc.valueAxis.valueStep = (value_max-value_min) // 5 # 设置y坐标的步长
bc.categoryAxis.labels.dx = 2
bc.categoryAxis.labels.dy = -8
bc.categoryAxis.labels.angle = 20
bc.categoryAxis.categoryNames = ax
# 图示
leg = Legend()
leg.fontName = 'SimSun'
leg.alignment = 'right'
leg.boxAnchor = 'ne'
leg.x = 475 # 图例的x坐标
leg.y = 240
leg.dxTextSpace = 10
leg.columnMaximum = 3
leg.colorNamePairs = items
drawing.add(leg)
drawing.add(bc)
return drawing
# 绘制图片
@staticmethod
def draw_img(path, **kwargs):
d = Drawing()
# 0, 0, 100, 100 表示: (x, y, width, height)
x = kwargs.get('x_pos', 0)
y = kwargs.get('y_pos', 0)
width = kwargs.get('width', 200)
height = kwargs.get('height', 200)
d.add(DrawingImage(x, y, width, height, path))
# d.add(DrawingImage(50, -100, 400, 100, path2)) # 这里可以将y坐标修改为负值, 使其在文字底部
return d
# img = Image(path) # 读取指定路径下的图片
# img.drawWidth = 8*cm # 设置图片的宽度
# img.drawHeight = 5*cm # 设置图片的高度
# return img
@staticmethod
def csv_to_dict(file_path):
data = {}
with open(file_path, 'r') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
for key, value in row.items():
if key not in data:
data[key] = []
data[key].append(value)
return data
if __name__ == '__main__':
gen_pdf = Graphs()
my_info = gen_pdf.csv_to_dict(file_path='/Users/monkey/Desktop/杂项/belle/code/my_info/基本信息.csv')
# 创建内容对应的空列表
content = list()
# 添加标题
content.append(Graphs.draw_title(f'{my_info["姓名"][0]}成长统计'))
# 写入个人信息为表格
content.append(gen_pdf.draw_little_title('个人信息[此处可以自己添加一些文字, 这里只做个人信息读取样例]'))
data = [
['姓名', '性别', '入学日期', '班级'],
['侯敬宇', '男', '2017/9/10', '软件1703']
]
content.append(gen_pdf.draw_table(*data))
class_info = gen_pdf.csv_to_dict(file_path='/Users/monkey/Desktop/杂项/belle/code/my_info/上课.csv')
score_info = dict()
for i in range(len(class_info['课程'])):
class_name = class_info['课程'][i]
class_score = int(class_info['期末考试成绩'][i])
if class_name not in score_info:
score_info[class_name] = class_score
else:
score_info[class_name] = (score_info[class_name] + class_score) // 2
class_info['课时'] = [int(i) for i in class_info['课时']]
# 写入上课信息为表格
content.append(gen_pdf.draw_title('-'*50))
content.append(gen_pdf.draw_little_title('上课统计'))
content.append(gen_pdf.draw_text(text='在校期间', alignment=1))
content.append(gen_pdf.draw_text(text=f'你共学习了{len(set(class_info["课程"]))}门课', alignment=1))
content.append(gen_pdf.draw_text(text=f'累计{sum(class_info["课时"])}课时', alignment=1))
# 写入成绩信息为表格
max_class_name = ''
max_class_score = 0
data = [
['课程', '期末成绩平均分']
]
for n, s in score_info.items():
max_class_name = n if s > max_class_score else max_class_name
max_class_score = max(max_class_score, s)
data.append([n, s])
content.append(gen_pdf.draw_table(*data))
content.append(gen_pdf.draw_text(text=f'其中, 成绩最好的课是{max_class_name}', alignment=1))
content.append(gen_pdf.draw_text(text=f'获得了{max_class_score}分!', alignment=1))
content.append(gen_pdf.draw_text(text='加油! 相信一份耕耘一份收获', alignment=1))
# 处理吃饭的数据
food_info = gen_pdf.csv_to_dict(file_path='/Users/monkey/Desktop/杂项/belle/code/my_info/食堂.csv')
food_info['金额'] = [int(i) for i in food_info['金额']]
print(food_info)
# 处理每学年的消费金额
food_money_year_info = dict()
food_ck_name_info = dict()
for i in range(len(food_info['学年'])):
year = food_info['学年'][i]
ck_name = food_info['窗口'][i]
money = int(food_info['金额'][i])
if year not in food_money_year_info:
food_money_year_info[year] = money
else:
food_money_year_info[year] += money
if ck_name not in food_ck_name_info:
food_ck_name_info[ck_name] = 1
else:
food_ck_name_info[ck_name] += 1
content.append(gen_pdf.draw_title('-'*50))
content.append(gen_pdf.draw_little_title('食堂统计信息'))
content.append(gen_pdf.draw_img('/Users/monkey/Desktop/杂项/belle/code/my_info/food1.jpg', '/Users/monkey/Desktop/杂项/belle/code/my_info/bg.jpg'))
content.append(gen_pdf.draw_text(text='在校期间', alignment=1))
content.append(gen_pdf.draw_text(text=f'你共在食堂用餐{len(food_info["学年"])}次', alignment=1))
content.append(gen_pdf.draw_text(text=f'累计消费{sum(food_info["金额"])}元', alignment=1))
# 生成图表
content.append(Graphs.draw_little_title('年度消费情况'))
y_data = [list(food_money_year_info.values())]
x_data = list(food_money_year_info.keys())
leg_items = [[colors.red, '消费金额']]
content.append(gen_pdf.draw_bar(y_data, x_data, leg_items, value_max=max(food_money_year_info.values())*2))
content.append(Graphs.draw_little_title('窗口消费次数分布情况'))
y_data = [list(food_ck_name_info.values())]
x_data = list(food_ck_name_info.keys())
leg_items = [[colors.red, '消费次数']]
content.append(gen_pdf.draw_bar(y_data, x_data, leg_items, value_max=max(food_ck_name_info.values())*2))
# 生成pdf文件
doc = SimpleDocTemplate(f'{my_info["姓名"][0]}.pdf', pagesize=letter)
doc.build(content)
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/monkey_hjy/gen_pdf.git
git@gitee.com:monkey_hjy/gen_pdf.git
monkey_hjy
gen_pdf
gen_pdf
main

搜索帮助