基于企业模板的 PPT 生成
概述
把结构化内容(大纲 / Markdown / 文档)生成风格统一、可编辑的 PowerPoint 文件。核心原则:
> 加载真实企业模板 + 代码填充内容,绝不自建模板。
模板自带母版、配色、Logo、背景(如「某企业 Logo + 品牌主色背景」),生成的 PPT 与人工制作视觉一致,且每一页都能在 PowerPoint 里二次编辑。
已验证战绩:19 页系统介绍 PPT(封面 + 目录 + 16 内容页 + 结束页),基于「某 AI 大赛官方 PPT 模板」生成,含表格、双截图卡片、成本对比条等复杂版式。
技术选型
| 方案 | 结论 |
|---|---|
| python-pptx(本技能) | ✅ 沙箱可用,纯代码、可控、可数据驱动;能完整保留模板母版 |
| 腾讯文档 / 腾讯文档 slide 类 | ❌ 沙箱 + 网络限制,连不上;放弃 |
| 纯代码画版式冒充模板 | ❌ 用户明确禁止(视觉不对、无企业 Logo) |
依赖:pip install python-pptx pillow pywin32(pywin32 仅用于导出预览图,可选)
适用场景
- 系统 / 产品 / 项目介绍 PPT
- 参赛路演材料(AI 大赛、创新大赛等,必须用官方模板)
- 政企客户汇报、方案宣讲
- 把 Markdown / Word 大纲转成规范 PPT
- 需要批量套版(同一模板换内容出多份)
核心心法(两条命门)
命门 1:模板驱动,绝不自建
from pptx import Presentation
from ppt_kit import *
prs = Presentation('你的模板.pptx') # ← 加载模板,母版/背景/Logo 自动保留
# 封面/目录/结束页:直接改模板里的占位符
find_shape(prs.slides[0], '标题 1').text_frame # 找占位符填字
# 内容页:复制模板里的一页当容器
s = duplicate_slide(prs, 2) # 复制模板第 3 页(index=2)
duplicate_slide 是灵魂:它先按模板版式新建一页(清掉默认占位符),再把源页所有形状深拷贝进去,既保留背景又给你一个干净容器填内容。
命门 2:中文字体必须写 a:ea
# ppt_kit.set_run 已处理,关键是调用它(不要直接 r.text = ...)
r.text = '中文' # ❌ 打开后回退宋体
set_run(r, '中文', 18, True) # ✅ 显式写入 a:ea 东亚字体
python-pptx 默认不写东亚字体声明,程序生成的 PPT 在 PowerPoint 里中文会回退到宋体。所有文本必须经 set_run / fill_tf 走一遭。
四步流程
第 1 步:研究模板(只做一次)
python inspect_template.py "模板.pptx" template_preview
输出:版式名称清单 + 每页预览图。重点记:
- 封面 / 目录 / 内容页 / 结束页分别在哪个 index
- 占位符的名字(标题 1、文本占位符 4 等)—— 用 find_shape(slide, 名字) 填
纯 python-pptx 也能读占位符(无需 PowerPoint):
prs = Presentation('模板.pptx')
for sh in prs.slides[0].shapes:
print(sh.name, sh.shape_type, 'has_tf=', bool(sh.has_text_frame))
第 2 步:组织内容
把要讲的内容整理成「一页一个主题」的清单。每页标注:
- 用哪个模板页作底(index)
- 标题 + 要点 / 表格 / 截图
第 3 步:写生成脚本
from pptx import Presentation
from ppt_kit import *
prs = Presentation('模板.pptx')
SW = prs.slide_width / 914400 # 画布宽(英寸),16:9 通常 13.333
SH = prs.slide_height / 914400 # 高 7.5
ML, CW = 0.6, SW - 1.2 # 左边距 + 内容可用宽
# 封面
fill_tf(find_shape(prs.slides[0], '标题 1').text_frame,
[L('系统名称', 40, True, BLUE)])
# 内容页(复制模板第 3 页当容器)
for page in CONTENT:
s = duplicate_slide(prs, 2)
fill_tf(find_shape(s, '标题 1').text_frame, [L(page['title'], 30, True, BLUE)])
draw_table(s, ML, 3.0, [2.0, 4.0], page['rows']) # 表格
# 截图
add_pic(s, page['img'], 7.0, 3.0, 5.0)
prs.save('out.pptx')
第 4 步:导出预览 + 视觉核验
python inspect_template.py out.pptx preview_out # 用 PowerPoint COM 导出 1280×720 图
必须逐页看预览图检查:文字溢出、字体回退、表格错位、图片比例。改完重跑脚本即可。
版面经验值(16:9 画布 13.333×7.5)
| 元素 | 字号 | 说明 |
|---|---|---|
| 封面主标题 | 36~40pt | 粗体、主题蓝 |
| 内容页标题 | 28~32pt | 粗体 |
| 卡片小标题 | 13~15pt | 金/蓝强调 |
| 卡片正文 | 11~13pt | 行距 1.2~1.4 |
| 表格文字 | 10.5pt / 表头 11pt | 表头白字蓝底,隔行浅蓝 |
| 边距 | 0.6 英寸 | 内容宽 ≈ 12.13 |
卡片式版式是主力:用 add_rect 画色块 + add_text 放文字,组合成「痛点卡 / 数据卡 / 对比卡」。比原生占位符好控位置。
工具集(scripts/ppt_kit.py)
from ppt_kit import * 即用:
| 函数 | 用途 |
|---|---|
set_run(r, text, size, bold, color, name) |
设文本+字体,写入 a:ea 中文字体 |
fill_tf(tf, lines, ...) |
用结构化 lines 重写 text_frame(清空旧内容) |
find_shape(slide, name) |
递归按名找形状(含 group 内) |
duplicate_slide(prs, index) |
复制模板页作新容器(保留背景) |
add_rect / add_text / add_pic |
画卡片/文字框/按比例插图 |
draw_table(sl, x, y, col_w, rows, ...) |
拼装表格(蓝头、隔行浅蓝) |
move_slide_last(prs, i) |
把某页移到最后(结束页) |
L(t, s, b, c, a) |
快捷构造单行文本 dict |
踩坑清单
完整版见 references/pitfalls.md,高频几条:
- 中文回退宋体:必须走
set_run写 a:ea,不能直接r.text= - 禁用腾讯文档类:沙箱连不上,统一 python-pptx
- 禁止自建模板:用户有真实企业模板,套版不重画
set_run用法:set_run(r, text, size, ...)—— 先r=p.add_run()再传入,别把 size 当 text 传(会报'float' object is not iterable)- 字体文件:中文字体用
微软雅黑(系统自带msyh.ttc) - 删除旧 pptx:环境禁止
os.remove(safe-delete),重跑用prs.save()直接覆盖同名文件即可
触发词
「做个 PPT」「按 XX 模板生成」「把大纲转成 PPT」「套公司模板出 slides」「路演材料」「项目汇报 PPT」「系统介绍演示文稿」
与其它技能协作
- 需要配套 Word 文档:用
md2docx_outline.py(Markdown→Word,同样处理中文字体w:eastAsia) - 需要从 PPT 生成讲解视频:属另一环节(本技能只负责 PPT 制作)