PPTX 邮件合并批量生成器 · SKILL
§0 三步快速开始
# 第一步:扫描模板中的图表(自动输出 Shape 索引和 Series 信息)
python ppt_mailmerge.py --scan --template "模板.pptx"
# 第二步:校验配置是否正确(不生成文件)
python ppt_mailmerge.py --excel "数据.xlsx" --template "模板.pptx" --config "映射.json" --output "./输出" --dry-run
# 第三步:正式批量生成
python ppt_mailmerge.py --excel "数据.xlsx" --template "模板.pptx" --config "映射.json" --output "./输出"
三步走:
1. 用 --scan 自动扫描模板中所有图表,获取 Shape 索引和 Series 名称,直接填入配置
2. 用 --dry-run 校验配置映射是否匹配模板,确认无误
3. 正式执行,按 key_column 逐行生成独立 PPTX 文件
§1 输入采集
1.1 CLI 参数
| 参数 | 必填 | 说明 |
|---|---|---|
--excel |
是* | Excel 数据源路径 |
--template |
是* | PPTX 模板路径 |
--output |
是* | 输出目录 |
--config |
否 | JSON 配置文件路径 |
--start N |
否 | 从第 N 行开始(0-based),断点续传 |
--count N |
否 | 仅处理 N 条,配合 --start 分片 |
--scan |
否 | 扫描模板图表,输出 Shape 索引和 Series |
--dry-run |
否 | 仅校验配置正确性,不生成文件 |
> ** --scan 模式下仅需 --template;--dry-run 和批量生成模式需 --excel + --template + --output。
1.2 Python API 调用
from ppt_mailmerge import batch_generate, scan_charts, ConfigError
# 扫描图表
charts = scan_charts("模板.pptx")
for c in charts:
print(f"Shape[{c['shape_idx']}] {c['shape_name']}: {c['categories']}")
# 校验配置
try:
batch_generate("数据.xlsx", "模板.pptx", "./输出", "映射.json", dry_run=True)
except ConfigError as e:
print(f"配置错误: {e}")
# 批量生成
files = batch_generate("数据.xlsx", "模板.pptx", "./输出", "映射.json")
print(f"共生成 {len(files)} 个文件")
1.3 JSON 配置结构
{
"excel": {"sheet": 0, "header_row": 1, "data_start_row": 2, "key_column": "姓名"},
"ppt": {
"text_mappings": {"姓名": "张XX", "总分": "360.0"},
"paragraph_mappings": [
{"excel_column": "综合评价", "search_keyword": "该员工", "min_length": 20, "table_match": "评价"}
],
"chart_mappings": {
"0": {"columns": ["Q1","Q2","Q3","Q4"], "series_name": "个人数据"}
}
},
"output": {"naming": "{idx:03d}-{姓名}-报告.pptx"}
}
1.4 输出命名
{idx:03d} 为流水号(从 1 开始,3 位补零),{姓名} 为 Excel 中 key_column 对应值。支持任意 Python format 语法。
§2 核心机制
2.1 三种映射类型
| 映射类型 | JSON 路径 | 行为 | 典型场景 |
|---|---|---|---|
| 文本占位符 | ppt.text_mappings |
Excel 某列 → PPT 中所有匹配的文本占位符,逐 run 替换 | 姓名、分数、日期等短值 |
| 段落评价 | ppt.paragraph_mappings |
Excel 某列文本 → PPT 中含关键词且长度≥min_len的段落,整段替换 | 综合评价、个人优势等长文本 |
| 图表数据 | ppt.chart_mappings |
Excel 多列 → 图表中指定 Series 的数据值 | 能力维度雷达图、柱状图 |
2.2 文本占位符详解
text_mappings 中 key 为 Excel 列名,value 为模板中对应的占位符文本。脚本遍历所有幻灯片的所有文本框,对每个 run 做精确匹配替换。注意:
- 占位符应唯一,避免 "60" 和 "360" 这样的包含关系导致误替换
- 模板中填入真实外观的样本数据(如"张XX"而非"{{姓名}}"),保证视觉一致性
- 若占位符在 PPT 中未匹配到,--dry-run 会发出警告;正式生成时静默跳过
2.3 段落评价详解
| 字段 | 类型 | 说明 |
|---|---|---|
excel_column |
str | Excel 列名,读取评价/描述文本 |
search_keyword |
str | PPT 目标段落中必须包含的关键词(不含标点更可靠) |
min_length |
int | 段落最少字符数,防止误匹配短标题。建议设为预估段落长度 × 0.6 |
table_match |
str(可选) | 若目标段落在表格内,填表格首单元格关键词以缩小匹配范围 |
常见陷阱:若 search_keyword 在段落中跨 run 拆分(PPT 中一个词分散在多个 run),将无法匹配。解决:PPT 中重新输入关键词文本确保在同一 run 内。
2.4 图表数据详解(--scan 一键获取索引)
图表映射 key 为 shape 索引(0-based),配置项:
- columns:Excel 列名数组,顺序须与图表 categories 一致
- series_name:要更新的 Series 名称
铁律:仅修改指定 Series 的数据值(Series[0] 个人数据)。图表标题、轴标签、分类名称、参考线(Series[1] 均值/基准)、颜色、图例等全部原样保留。
自动扫描(推荐):
python ppt_mailmerge.py --scan --template "模板.pptx"
输出示例:
Slide[0] Shape[7] 图表 1
分类: ['政治认知', '廉洁自律', '大局意识', '担当作为']
Series「个人得分」: [85.0, 90.0, 78.0, 88.0]
chart_mappings 配置示例:
{"7": {"columns": ["政治认知","廉洁自律","大局意识","担当作为"], "series_name": "个人得分"}}
将输出中的配置示例直接复制到 JSON 配置即可。
2.5 依赖与安装
脚本自动检测并安装缺失依赖(python-pptx, openpyxl),无需手动操作。
§R 铁律
- 配置为王:所有映射关系以 JSON 配置文件为准,脚本不做硬编码推断
- 模板不可变:每次从原始模板文件加载,不修改模板本身
- 图表最小改动:只改指定 Series 的数值,结构文本不碰
- 内容来源唯一:所有文字内容从 Excel 列读取,脚本自身不生成任何文字
- key_column 必存在:必须在 Excel 表头中存在,否则终止
- 独立运行:不依赖任何其他 Skill,可独立完成 PPT 邮件合并任务
§A 异常处理
| 异常 | 级别 | 处理方式 |
|---|---|---|
| Excel/PPTX/配置文件不存在 | 致命 | 终止运行,输出清晰的路径错误提示 |
| key_column 表头找不到 | 致命 | 终止运行,列出 Excel 中所有可用列名 |
| 配置 JSON 格式错误 | 致命 | 终止运行,提示具体解析位置 |
| text_mappings 占位符未匹配 | 警告 | dry-run 时显式警告,正式运行时静默跳过 |
| chart_mappings shape 索引越界/非图表 | 致命 | dry-run 时立即报错,含具体 shape 位置 |
| paragraph_mappings 关键词未匹配 | 警告 | dry-run 时显式警告 |
| 单条数据处理异常 | 警告 | 跳过该条数据并记录行号,继续下一条 |
| python-pptx/openpyxl 缺失 | 自动修复 | 自动 pip install 后重试 |
§B FAQ
Q: 图表 Shape 索引怎么找?
A: python ppt_mailmerge.py --scan --template "模板.pptx" 一键输出所有图表的索引、分类名和 Series 信息,直接复制到配置即可。
Q: 占位符设计原则?
A: 模板中用真实外观的样本数据(如"张XX"/"85.0"),配置中声明 Excel 列名 → 样本值映射。避免占位符之间存在包含关系(如同时有"60"和"360")。
Q: 段落替换不生效怎么办?
A: 依次排查:① --dry-run 校验,确认 keyword 是否匹配到(不含标点更可靠);② 段落长度是否 ≥ min_length;③ 检查 PPT 中 keyword 是否跨 run 拆分(重新输入解决);④ 若在表格内,确认 table_match 正确。
Q: 配置对不对不确定?
A: 先跑 --dry-run,脚本会逐项校验 text_mappings / chart_mappings / paragraph_mappings 是否有效匹配模板,致命错误会立即终止并指出具体位置。
Q: 图表有多个 Series,如何只改其中一个?
A: 通过 series_name 精确指定。未匹配到的 Series(如均值参考线)原样保留。
Q: 如何处理大量数据?
A: 单条处理约 0.5~1 秒。建议先用 --dry-run 校验,再用 --count 10 试跑验证,最后全量执行。
Q: 想在 Python 代码中调用而不是命令行?
A: 直接 from ppt_mailmerge import batch_generate, scan_charts,详见 §1.2 Python API 调用示例。
§C 常见陷阱与最佳实践
| 陷阱 | 表现 | 解决 |
|---|---|---|
| chart_mappings 索引填错 | 图表未更新,无报错 | 用 --scan 确认索引 |
| 占位符存在包含关系 | "360" 被 "60" 先替换,变成 "3新值" | 占位符设计时避免子串包含,或用独特文本(如 "360分" 而非 "360") |
| keyword 跨 run 拆分 | 段落替换不生效 | PPT 中选中关键词文本,重新输入一次 |
| min_length 设太高 | 段落不匹配 | 设为预估段落长度 × 0.6 |
| Excel 有空行/汇总行 | 生成内容异常 | Excel 数据源中删除汇总行和空行 |
| 图表 categories 顺序与 Excel columns 不一致 | 图表数据错位 | 严格按 --scan 输出的 categories 顺序填写 columns |
§D 完整示例
Excel(销售测评.xlsx):
| 姓名 | 沟通 | 谈判 | 客户管理 | 团队协作 | 业绩达成 | 总分 | 综合评价 |
|---|---|---|---|---|---|---|---|
| 张XX | 85 | 92 | 78 | 88 | 90 | 433 | 该员工谈判能力突出… |
| 李XX | 90 | 88 | 95 | 92 | 85 | 450 | 整体能力均衡… |
命令:
python ppt_mailmerge.py --excel "销售测评.xlsx" --template "报告模板.pptx" --config "映射.json" --output "./输出"
输出:
./输出/
001-张XX-销售测评报告.pptx
002-李XX-销售测评报告.pptx
§E 边界与限制
- 图表仅支持 Series 数据值替换,不支持新增/删除 Series 或修改图表类型
- 文本替换是精确 run-level 匹配,不支持正则或模糊匹配
- 段落替换仅支持 Shape 内段落和表格内段落,不支持 SmartArt 内文本
- 输出的 PPTX 格式由 python-pptx 库决定,可能与原模板有微小差异
- 不支持跨幻灯片引用、母版修改、动画/切换效果保留