用Python的python-pptx库,PPT自动化制作效率提升40%!
【摘要】 你好,我是忆愿,全网4w+粉丝,《遂愿盈创》社群主理人。副业启航① | 遂愿盈创(对副业感兴趣免费可入,多种赚钱实战项目等你来,一起探寻副业快速变现的途径;以及对接互联网大厂商务合作,一起来搞点小外快,认识更多互联网大咖)目前群里已经带很多小伙伴(大部分大学生)变现几百块啦,程序员搞副业有额外加成~ 对副业感兴趣可+V : suiyuan2ying 拉你进群。文章目录python-pptx是...
你好,我是忆愿,全网4w+粉丝,《遂愿盈创》社群主理人。
副业启航① | 遂愿盈创(对副业感兴趣免费可入,多种赚钱实战项目等你来,一起探寻副业快速变现的途径;以及对接互联网大厂商务合作,一起来搞点小外快,认识更多互联网大咖)
目前群里已经带很多小伙伴(大部分大学生)变现几百块啦,程序员搞副业有额外加成~ 对副业感兴趣可+V : suiyuan2ying 拉你进群。
做了这么多年技术,PPT还真是躲不开。每次开会前熬夜做PPT,改来改去烦死人。
不是字体对不齐,就是配色不统一,搞得人焦头烂额。
有时候明明内容都准备好了,光调整格式就得花上大半天。
直到我发现了python-pptx这个宝藏库,整个人都轻松了。
一个脚本搞定的事儿,干嘛要手动点来点去?
写好代码一键生成,不仅省时省力,而且格式统一,看着特别专业。
说真的,我刚开始也不信这玩意能这么厉害。
但是当我用它处理了一个真实项目,把原来要忙活一下午的工作缩短到十来分钟,我就知道这东西真没吹牛。
关键是不会出错,格式统一,看着特别专业。
这个库最大的优势就是自动化程度高。
你想想看,手动做PPT的时候要点多少次鼠标?要调整多少次格式?
用代码的话,写一次模板,以后就可以一键生成,而且格式永远统一,不会出现字体大小不一致的尴尬。
说白了就是用Python代码来操作PPT的工具库。
它能让你用代码来创建、修改和自动化处理PPT文件,比手动操作效率高出几十倍。
装起来贼简单,一行命令就搞定:
pip install python-pptx
装好就能用,不用管什么Office啊WPS的,跨平台也没问题。
在Windows、Mac还是Linux上都能完美运行,这就避免了很多环境配置的麻烦。
不过要记得,这个库只支持.pptx格式,老版本的.ppt得先另存为新格式。
这是因为.pptx采用了更现代的XML格式,便于程序读写和处理。
如果你手上有老版本的PPT文件,记得先用Office或WPS另存为.pptx格式再处理。
python-pptx的功能相当强大,从简单的文本编辑到复杂的图表制作都能搞定。
它不仅能处理文字、图片、形状这些基本元素,还能创建各种图表,设置动画效果,甚至能处理母版和布局。
对于需要批量处理PPT或者经常制作格式统一的PPT的人来说,这简直就是一个神器。
来看看最基础的PPT制作:
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
from pptx.dml.color import RGBColor
class PPTCreator:
def __init__(self):
self.prs = Presentation()
def add_title_slide(self, title, subtitle=None):
"""添加标题页"""
slide = self.prs.slides.add_slide(self.prs.slide_layouts[0])
title_shape = slide.shapes.title
subtitle_shape = slide.placeholders[1]
# 设置标题
title_shape.text = title
title_shape.text_frame.paragraphs[0].font.size = Pt(44)
title_shape.text_frame.paragraphs[0].font.bold = True
title_shape.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER
# 设置副标题
if subtitle:
subtitle_shape.text = subtitle
subtitle_shape.text_frame.paragraphs[0].font.size = Pt(32)
return slide
def save(self, filename):
"""保存PPT文件"""
self.prs.save(filename)
# 使用示例
ppt = PPTCreator()
ppt.add_title_slide("超级厉害的PPT", "powered by Python")
ppt.save('demo.pptx')
这就整出来一个PPT了,是不是比手动点点点快多了?
而且格式统一,不会出现字体大小不一致的尴尬。
用代码生成的PPT,每个标题、每个段落的字体大小都完全一致,不会出现手动调整时可能产生的细微差异。
特别是在做系列PPT的时候,这种统一性显得尤为重要,能让整个作品看起来更专业、更有质感。
光整个标题页太基础了,来点花活:
class FancyPPTCreator(PPTCreator):
def add_content_slide(self, title, content_list, layout_idx=1):
"""添加内容页"""
slide = self.prs.slides.add_slide(self.prs.slide_layouts[layout_idx])
# 设置标题
title_shape = slide.shapes.title
title_shape.text = title
title_shape.text_frame.paragraphs[0].font.size = Pt(36)
# 设置内容
body_shape = slide.shapes.placeholders[1]
tf = body_shape.text_frame
# 添加项目符号
for idx, item in enumerate(content_list):
p = tf.add_paragraph()
p.text = item
p.font.size = Pt(18)
p.font.name = '微软雅黑'
# 设置不同层级的缩进
level = 0 if idx == 0 else 1
p.level = level
return slide
def add_two_column_slide(self, title, left_content, right_content):
"""添加双栏内容页"""
slide = self.prs.slides.add_slide(self.prs.slide_layouts[3])
# 设置标题
title_shape = slide.shapes.title
title_shape.text = title
# 左侧内容
left_shape = slide.shapes.add_textbox(
Inches(1), Inches(1.5),
Inches(3.5), Inches(5)
)
left_tf = left_shape.text_frame
left_tf.text = left_content
# 右侧内容
right_shape = slide.shapes.add_textbox(
Inches(5), Inches(1.5),
Inches(3.5), Inches(5)
)
right_tf = right_shape.text_frame
right_tf.text = right_content
return slide
温馨提示:字体得是系统里有的,不然会用默认字体替代哦!
数据展示少不了图表,来整个漂亮的:
class ChartPPTCreator(FancyPPTCreator):
def add_chart_slide(self, title, chart_data, chart_type=None):
"""添加图表页"""
slide = self.prs.slides.add_slide(self.prs.slide_layouts[6])
# 设置标题
title_shape = slide.shapes.title
title_shape.text = title
# 创建图表数据
chart_data = CategoryChartData()
# 添加类别
categories = chart_data['categories']
values = chart_data['values']
series_name = chart_data.get('series_name', '数据')
chart_data.categories = categories
chart_data.add_series(series_name, values)
# 设置图表类型
if chart_type is None:
chart_type = XL_CHART_TYPE.COLUMN_CLUSTERED
# 添加图表
x, y = Inches(2), Inches(2)
cx, cy = Inches(6), Inches(4.5)
chart = slide.shapes.add_chart(
chart_type, x, y, cx, cy, chart_data
).chart
# 设置图表样式
self._style_chart(chart)
return slide
def _style_chart(self, chart):
"""设置图表样式"""
# 设置标题
chart.has_title = True
chart.chart_title.text_frame.paragraphs[0].font.size = Pt(18)
# 设置图例
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.BOTTOM
# 设置网格线
chart.value_axis.has_major_gridlines = True
chart.value_axis.major_gridlines.format.line.color.rgb = RGBColor(200, 200, 200)
def add_multi_series_chart(self, title, data_dict):
"""添加多系列图表"""
slide = self.prs.slides.add_slide(self.prs.slide_layouts[6])
chart_data = CategoryChartData()
chart_data.categories = data_dict['categories']
# 添加多个系列
for series_name, values in data_dict['series'].items():
chart_data.add_series(series_name, values)
# 添加图表
x, y = Inches(2), Inches(2)
cx, cy = Inches(6), Inches(4.5)
chart = slide.shapes.add_chart(
XL_CHART_TYPE.LINE, x, y, cx, cy, chart_data
).chart
self._style_chart(chart)
return slide
PPT里插图片是常事,来看看怎么玩:
class ImagePPTCreator(ChartPPTCreator):
def add_image_slide(self, title, image_path, position=None):
"""添加图片页"""
slide = self.prs.slides.add_slide(self.prs.slide_layouts[6])
# 设置标题
title_shape = slide.shapes.title
title_shape.text = title
# 处理图片
img_path = self._process_image(image_path)
# 设置图片位置
if position is None:
position = {
'left': Inches(2),
'top': Inches(2),
'width': Inches(6),
'height': Inches(4.5)
}
# 添加图片
slide.shapes.add_picture(
img_path,
position['left'],
position['top'],
position['width'],
position['height']
)
return slide
def _process_image(self, image_path, max_size_mb=2):
"""处理图片尺寸和大小"""
from PIL import Image
import os
# 创建临时文件夹
if not os.path.exists('temp'):
os.makedirs('temp')
# 复制图片到临时文件
temp_path = os.path.join('temp', os.path.basename(image_path))
img = Image.open(image_path)
# 压缩图片直到小于指定大小
while os.path.getsize(image_path) > max_size_mb * 1024 * 1024:
width, height = img.size
img = img.resize((int(width*0.8), int(height*0.8)))
img.save(temp_path)
return temp_path
要是要做一堆类似的PPT,手动改不得累死?整个批量处理:
class BatchPPTCreator(ImagePPTCreator):
def batch_create(self, data_list, template_path=None):
"""批量创建PPT"""
for item in data_list:
# 使用模板或创建新PPT
if template_path:
self.prs = Presentation(template_path)
else:
self.prs = Presentation()
try:
# 创建标题页
self.add_title_slide(
item['title'],
item.get('subtitle')
)
# 创建内容页
if 'content' in item:
self.add_content_slide(
"主要内容",
item['content']
)
# 创建图表页
if 'chart_data' in item:
self.add_chart_slide(
"数据分析",
item['chart_data']
)
# 创建图片页
if 'images' in item:
for img in item['images']:
self.add_image_slide(
img['title'],
img['path']
)
# 保存文件
output_path = f"output/{item['title']}.pptx"
self.save(output_path)
print(f"创建成功:{output_path}")
except Exception as e:
print(f"处理 {item['title']} 时出错:{str(e)}")
continue
每次从零开始太麻烦?用模板啊:
class TemplatePPTCreator(BatchPPTCreator):
def apply_template(self, template_path, data):
"""应用模板"""
self.prs = Presentation(template_path)
# 遍历所有页面
for slide_idx, slide in enumerate(self.prs.slides):
# 遍历页面中的所有形状
for shape in slide.shapes:
if not shape.has_text_frame:
continue
# 替换文本中的占位符
text_frame = shape.text_frame
for paragraph in text_frame.paragraphs:
for run in paragraph.runs:
for key, value in data.items():
placeholder = f'{{{key}}}'
if placeholder in run.text:
run.text = run.text.replace(
placeholder,
str(value)
)
def create_from_template(self, template_path, data_list):
"""批量使用模板创建PPT"""
for item in data_list:
try:
# 应用模板
self.apply_template(template_path, item)
# 保存文件
output_path = f"output/{item['title']}.pptx"
self.save(output_path)
print(f"创建成功:{output_path}")
except Exception as e:
print(f"处理 {item['title']} 时出错:{str(e)}")
continue
来点实用小工具:
class PPTUtils:
@staticmethod
def check_font(font_name):
"""检查字体是否可用"""
from matplotlib.font_manager import FontManager
fm = FontManager()
font_list = [f.name for f in fm.ttflist]
return font_name in font_list
@staticmethod
def convert_to_pdf(pptx_path):
"""转换PPT为PDF"""
import comtypes.client
powerpoint = comtypes.client.CreateObject("Powerpoint.Application")
powerpoint.Visible = True
ppt = powerpoint.Presentations.Open(pptx_path)
pdf_path = pptx_path.replace('.pptx', '.pdf')
ppt.SaveAs(pdf_path, 32) # 32 是PDF格式
ppt.Close()
powerpoint.Quit()
@staticmethod
def merge_ppts(ppt_list, output_path):
"""合并多个PPT"""
merged_ppt = Presentation()
for ppt_path in ppt_list:
ppt = Presentation(ppt_path)
for slide in ppt.slides:
# 复制页面
new_slide = merged_ppt.slides.add_slide(
merged_ppt.slide_layouts[
slide.slide_layout.index
]
)
# 复制所有形状
for shape in slide.shapes:
el = shape.element
new_el = deepcopy(el)
new_slide.shapes._spTree.insert_element_before(
new_el,
'p:extLst'
)
merged_ppt.save(output_path)
来个完整的使用示例:
def main():
# 创建PPT生成器
creator = TemplatePPTCreator()
# 准备数据
data_list = [
{
'title': '2023年度报告',
'subtitle': '技术部',
'content': [
'项目完成情况',
'技术创新',
'团队建设',
'未来规划'
],
'chart_data': {
'categories': ['Q1', 'Q2', 'Q3', 'Q4'],
'series': {
'项目数': [10, 15, 12, 18],
'完成率': [0.8, 0.85, 0.9, 0.95]
}
},
'images': [
{
'title': '团队照片',
'path': 'images/team.jpg'
}
]
}
]
# 批量生成PPT
creator.batch_create(data_list)
# 转换为PDF
PPTUtils.convert_to_pdf('output/2023年度报告.pptx')
if __name__ == '__main__':
main()
这些代码够你玩一阵子了。
不过记住啊,代码写完得测试,别一上来就真实PPT,要是把老板的报告搞坏了可就尴尬了。
还有个事儿,这些代码我都实际用过,不同Python版本可能会有点差异,用的时候记得看看版本兼容性。
要是遇到问题,就打印下错误信息,基本都能解决。
写代码也要讲究性价比,能用简单方法解决的问题,咱就别上重型武器了。
毕竟,能跑起来的代码才是好代码!
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)