小张是个运营,每周五都要做数据周报。
每次打开PPT,新建一页,拖一个文本框进来,调字号、改字体、居中、加粗、换颜色……十几页PPT做下来,大半个下午就没了。
最烦的是,下周还要再来一遍。
她问我:“这些重复操作,能不能让代码帮我做?”
能。Python里有个库叫python-pptx,专门干这事儿。
你可能会想:“我连PPT都没玩明白,还让我写代码?”
别急。做PPT的重复操作,本质上就是三件事:在哪放文本框、写什么字、字长什么样。用代码写一遍,以后每次运行就行,连格式刷都省了。
先搭个最简单的框
你只需要四行代码,就能生成一个文本框。
from pptx import Presentation from pptx.util import Inches # 新建PPT(或者打开现有的) prs = Presentation() # 加一页空白幻灯片 slide = prs.slides.add_slide(prs.slide_layouts[6]) # 画个文本框:离左边1英寸,离上边1英寸,宽5英寸,高2英寸 textbox = slide.shapes.add_textbox(Inches(1), Inches(1), Inches(5), Inches(2)) # 写点字进去 textbox.text_frame.text = "我是自动生成的" # 保存 prs.save("我的第一个文本框.pptx")跑一下这段代码,打开生成的PPT,你会在空白页的左上角看到一个文本框。
这里有个概念叫“坐标系统”。PPT里所有东西的位置,都是用英寸(Inches)或者厘米(Cm)来定的。add_textbox的四个参数分别是:
left:离页面左边的距离
top:离页面上边的距离
width:文本框的宽度
height:文本框的高度
你可以把这些数字随便改,比如Inches(2)就是两英寸。改完再跑一遍,框的位置和大小就变了。
别把字都挤在一起:理解三层结构
你可能会遇到一个情况:在一个文本框里写了好几行字,想单独调整其中一行的样式,发现调不了。
这就涉及到python-pptx里文本的核心结构了。它有三层:
TextFrame(文本框容器):最外层,管整个框的行为,比如边距、垂直对齐、是否自动换行。
Paragraph(段落):中间层,管一段话的行为,比如对齐方式、行间距、项目符号层级。
Run(文字块):最内层,真正管文字长什么样,比如字体、字号、颜色、粗体斜体。
简单说:一个文本框里可以有多个段落,一个段落里可以有多个Run。
为什么要有Run?因为一段话里可能既有普通文字又有加粗红色文字。Run就是用来实现这种“混搭”的。
下面这段代码展示了这三层怎么配合:
from pptx import Presentation from pptx.util import Inches, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor prs = Presentation() slide = prs.slides.add_slide(prs.slide_layouts[6]) # 新建文本框 textbox = slide.shapes.add_textbox(Inches(1), Inches(1), Inches(8), Inches(3)) frame = textbox.text_frame # 第一段:普通段落 frame.text = "这是第一段" frame.paragraphs[0].alignment = PP_ALIGN.CENTER # 居中对齐 # 第二段:手动添加 p2 = frame.add_paragraph() p2.text = "这是第二段,有特殊格式:" # 在第二段里加一个Run,只让"重点"两个字变色 run = p2.add_run() run.text = "重点" run.font.bold = True run.font.color.rgb = RGBColor(255, 0, 0) # 红色 run.font.size = Pt(18) # 继续加普通文字 run2 = p2.add_run() run2.text = " 后面的普通文字" prs.save("三层结构演示.pptx")跑完这段,你会看到:第一段居中,第二段里“重点”两个字又大又红又粗,后面的文字保持原样。
这就是Run的威力——精细控制。
让文字更好看:字体、字号、颜色、对齐
做PPT的人都知道,好看的排版离不开这些细节。python-pptx基本都支持。
字体和字号:
run = frame.paragraphs[0].add_run() run.text = "Hello" run.font.name = "微软雅黑" # 字体名 run.font.size = Pt(24) # 字号,单位是磅粗体、斜体、下划线:
run.font.bold = True # 加粗 run.font.italic = True # 斜体 run.font.underline = True # 下划线颜色:
from pptx.dml.color import RGBColor # RGB颜色,三个数字分别代表红绿蓝,范围0-255 run.font.color.rgb = RGBColor(255, 0, 0) # 红色 run.font.color.rgb = RGBColor(0, 112, 192) # 一种蓝色段落对齐:
from pptx.enum.text import PP_ALIGN paragraph.alignment = PP_ALIGN.CENTER # 居中 paragraph.alignment = PP_ALIGN.LEFT # 左对齐 paragraph.alignment = PP_ALIGN.RIGHT # 右对齐文本框级别的设置(整个框的垂直对齐、边距、自动换行):
from pptx.enum.text import MSO_ANCHOR, MSO_AUTO_SIZE frame.vertical_anchor = MSO_ANCHOR.MIDDLE # 文字在框里垂直居中 frame.margin_left = Inches(0.2) # 左边距 frame.margin_top = Inches(0.1) # 上边距 frame.word_wrap = True # 自动换行 frame.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT # 根据文字自动调整框大小这些设置混在一起用,基本能实现PPT里95%的排版需求。
做出有层次感的文本:项目符号和多级列表
做PPT少不了要点列表。python-pptx支持自动生成项目符号,还能缩进。
from pptx import Presentation from pptx.util import Inches prs = Presentation() slide = prs.slides.add_slide(prs.slide_layouts[6]) textbox = slide.shapes.add_textbox(Inches(1), Inches(1), Inches(6), Inches(3)) frame = textbox.text_frame # 清空默认段落,自己从头加 frame.clear() # 加三个要点,层级不同 items = [ ("核心结论", 0), (" 营收增长25%", 1), (" 主要来自华东区", 2), (" 成本下降10%", 1), ] for text, level in items: p = frame.add_paragraph() p.text = text p.level = level # 0是最外层,数字越大缩进越多 # 默认就有项目符号,如果想关掉: # p.bullet = False prs.save("项目符号演示.pptx")跑完这段,你会看到一个有层级缩进的列表,就像Word里的多级列表一样。
一个完整例子:批量生成周报
现在把小张的需求串起来。假设她要生成一份周报,包含三部分:标题、核心数据(加粗红色)、分析结论(项目符号)。
from pptx import Presentation from pptx.util import Inches, Pt from pptx.enum.text import PP_ALIGN from pptx.dml.color import RGBColor def create_report(report_title, key_number, conclusions): prs = Presentation() # 封面页 slide = prs.slides.add_slide(prs.slide_layouts[6]) # 标题框 title_box = slide.shapes.add_textbox(Inches(1), Inches(2), Inches(8), Inches(1)) title_frame = title_box.text_frame title_frame.text = report_title title_frame.paragraphs[0].alignment = PP_ALIGN.CENTER title_frame.paragraphs[0].runs[0].font.size = Pt(32) title_frame.paragraphs[0].runs[0].font.bold = True # 核心数据框 data_box = slide.shapes.add_textbox(Inches(1), Inches(3.5), Inches(8), Inches(0.8)) data_frame = data_box.text_frame data_frame.text = f"核心数据:" run = data_frame.paragraphs[0].add_run() run.text = f" {key_number}" run.font.bold = True run.font.color.rgb = RGBColor(255, 0, 0) run.font.size = Pt(20) data_frame.paragraphs[0].alignment = PP_ALIGN.CENTER # 分析结论页 slide2 = prs.slides.add_slide(prs.slide_layouts[6]) box = slide2.shapes.add_textbox(Inches(1), Inches(1.5), Inches(8), Inches(4)) frame = box.text_frame frame.text = "分析结论:" frame.paragraphs[0].font.size = Pt(24) frame.paragraphs[0].font.bold = True for conclusion in conclusions: p = frame.add_paragraph() p.text = conclusion p.level = 0 p.font.size = Pt(16) prs.save("周报.pptx") print("周报生成成功!") # 调用函数 create_report( "第45周运营周报", "GMV突破500万", ["用户活跃度提升12%", "新客转化率创历史新高", "下周重点关注留存率"] )小张以后每周只需要改三个参数:标题、核心数字、结论列表。运行一下,几秒钟就能拿到一份格式统一的周报。
遇到模板怎么办?替换占位符
很多公司有自己的PPT模板,标题在固定位置,logo在固定位置。
python-pptx可以打开现有PPT,找到特定的占位符,替换里面的内容。
prs = Presentation("公司模板.pptx") slide = prs.slides[0] # 取第一页 # 遍历这一页上所有的占位符 for shape in slide.placeholders: print(f"占位符ID: {shape.placeholder_format.idx}, 名字: {shape.name}") # 根据索引替换 slide.placeholders[0].text = "2025年Q1汇报" slide.placeholders[1].text = "销售部" prs.save("填好内容的汇报.pptx")先跑一下打印占位符的代码,记下每个位置对应的ID,然后就可以用代码批量填充了。
几个容易踩的坑
坑一:修改已有文本框内容时,格式丢了
如果你拿到一个已有的文本框,直接text_frame.text = "新内容",里面的格式会被清空。想保留格式,应该操作具体的段落和Run。
坑二:中文字体显示成方块
必须指定系统里存在的字体。Windows用"微软雅黑"或"SimHei",Mac用"PingFang SC"。不指定的话,可能会用默认字体,中文就变成方块了。
坑三:文本框太小,字显示不全
设置text_frame.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT,文本框会自动撑大。或者设置text_frame.word_wrap = True让它自动换行。
坑四:添加多个段落时,第一段消失了
刚创建的文本框自带一个空段落。如果你调用add_paragraph()之前没有clear(),那第一段可能会被覆盖。保险做法:加内容之前先text_frame.clear()。
还能做什么?
掌握了文本框,python-pptx还能干更多事:
插入图片和表格
画各种形状(矩形、圆形、箭头)
读取现有PPT的内容
批量修改几十个PPT的页脚
比如给100份产品介绍PPT统一加上公司logo和联系方式,手改要半天,用代码两秒跑完。
回到小张。她现在每周五上午花两分钟改改参数,然后去倒杯咖啡,回来周报就生成好了。
她说:“以前觉得会写代码的人很酷,现在发现会写代码的自己更酷。”