PPTX 样式统一
Overview
对一份 PPTX 做两件事,全部由脚本确定性完成:
- 字体统一:全文档所有文字(含组合形状、表格内文字)的字体归一。中文字体通过设置
<a:ea>(东亚字体)生效,只设 latin 字体对中文无效——这是最常见的坑。 - 标题统一:识别每页的标题占位符,取正文页标题中出现频次最高的位置(左/上/宽/高)与样式(字号/加粗/颜色),统一应用到所有正文页标题。封面页自动识别并跳过。
使用流程
第 0 步:确认文件格式
只支持 .pptx。WPS 的 .dps / .ppt 需先让用户在 WPS 中「另存为 .pptx」。不要猜,直接问用户要 .pptx 或请其另存。
第 1 步:dry-run 预览(必做)
先跑 --dry-run,把报告给用户看,确认统一目标符合预期再落盘:
python3 scripts/unify_pptx.py <input.pptx> --dry-run
报告含:正文页起始页码(body_start_index)、统一前各页字体分布(fonts_before)、将采用的字体目标(fonts_applied)、缺标题的页(slides_missing_title)。
第 2 步:执行统一
# 默认:字体归一到文档内各自的主流字体(标题/正文分别统计),标题对齐到主流位置与样式
python3 scripts/unify_pptx.py <input.pptx>
# 指定字体
python3 scripts/unify_pptx.py <input.pptx> --title-font 微软雅黑 --body-font 等线
# 或全部统一为一个字体
python3 scripts/unify_pptx.py <input.pptx> --font 微软雅黑
# 指定标题样式(覆盖众数)
python3 scripts/unify_pptx.py <input.pptx> --title-size 28 --title-bold --title-color 1F4E79
# 指定标题位置(厘米,相对左上角;WPS 对象属性面板里看到的数字直接可用)
python3 scripts/unify_pptx.py <input.pptx> --title-left-cm 3 --title-top-cm 0.6
# 也可覆盖宽高:--title-width-cm 28 --title-height-cm 1.7
# 只动字体,不动标题
python3 scripts/unify_pptx.py <input.pptx> --no-align-title --keep-title-style
# 自定义正文起始页(默认自动识别封面)
python3 scripts/unify_pptx.py <input.pptx> --body-start 3
输出:<原名>_unified.pptx(不覆盖原文件)+ <原名>_unified_report.json(变更报告)。把报告要点转述给用户:改了多少个 run、对齐了几页标题、哪些页缺标题。
默认策略与判断依据
- 封面识别:第 1 页版式名含 title/标题/封面/cover,或含副标题占位符,则第 1 页为封面,从第 2 页起算正文页。可用
--body-start覆盖。仅当用户说明封面在别处时才需要覆盖。 - 字体目标:未指定时,标题与正文分别取出现频次最高的字体(run 级统计)。这意味着如果文档里已有两种字体 roughly 对半,需要用户拍板用哪个——dry-run 报告里看
fonts_before后问一句。 - 标题样式目标:取正文页标题的众数(位置按 EMU 精确匹配、字号/加粗/颜色按众数)。只有一页与其他不同时,会被拉齐到多数派——这是预期行为,报告里能看出来。
- 不改动:封面页的一切、无文字的占位符、备注页、图片/图表内文字。
已知边界
- 页标题选取策略(跨页位置投票 + 最顶部兜底 + 标题带扩搜):每页可能有多个名称含 Title/标题 的形状(卡片标签常命名为 business-0-title、Title 6、XX标题0)。选取顺序:
1. 命中「跨页出现最多的候选位置」的候选优先(真标题通常几十页同位);
2. 否则取最靠上的候选;若其位置明显低于标题带(众数标题 top+高度+0.15in),说明真标题可能是无关键词命名的文本框(如「矩形 1」),此时在标题带内扩搜有文字(≤30 字)的形状取最靠上者。
选取结果记录在报告title_selection.selected(页码 → 形状名,扩搜会标注「(扩搜)」),执行后应抽查该清单。 - 结尾/致谢页自动排除:任一候选文本含 感谢/谢谢/致谢/thanks(≤20 字)的页跳过标题处理,避免把 60pt 的「感谢聆听」拉成正文标题。记录在报告
closing_pages_skipped。 - 继承优先:统计样式众数时「无显式样式(继承母版)」也参与计数。若多数标题靠继承,目标即为继承,少数派的显式覆盖会被重置回继承,而不是把多数派强写成特例值。
- 标题识别依据占位符类型(TITLE / CENTER_TITLE)或形状名含 Title/标题。完全无候选的页记入
slides_missing_title(如伪标题矩形做的栏目页),不盲目扩搜;若需统一需人工确认目标形状。 - 不修改主题(theme)字体与母版;run 级覆盖已足够让显示效果一致,且不会破坏模板。
- WPS 的
.dps/.ppt先另存为.pptx。脚本依赖 python-pptx(本机已装 1.0.2)。
Resources
scripts/unify_pptx.py— 核心脚本,直接执行,无需读入上下文;需要改动行为时先读再改。