PPTX 批量页码重编
何时用
用户给一个 .pptx,要求修正/统一右下角页码(形如 02 / 71)。典型症状:序号与所在页错位、分母不统一、位置漂移、部分页缺页码框。
铁律
- 必须先走
tencent-docs-routing→tencent-local-office-edit,用edsdk.py调 slide 工具,不要用 python-pptx 直接改。 - 一个脚本干完一件事:editor_sdk 实例闲置会被回收(隔几十秒再调用报
page_index out of range [0, 0))。所以「打开→扫描→执行→保存→校验」必须写在同一个脚本进程里,不能分多次对话调用。每个脚本开头都带ensure_open()。 - 动手前必须问清三件事:编号规则(物理页序 / 只算正文页)、缺页码页是否补、位置是否统一。用户往往还有隐含预期(如深色页页码要浅色)。
脚本骨架
SKILL = r"D:\Workbuddy\resources\app.asar.unpacked\resources\plugins\workbuddy-builtin\skills\tencent-local-office-edit"
FID = r"<绝对路径>.pptx"
def call(tool, **kw): # 调 edsdk.py 并解析最后一行 JSON
args = [sys.executable, "edsdk.py", "call", tool, "file_id=" + FID]
for k, v in kw.items(): args.append("%s=%s" % (k, v))
p = subprocess.run(args, cwd=SKILL, capture_output=True)
for ln in reversed(p.stdout.decode("utf-8","replace").splitlines()):
if ln.strip().startswith("{"): return json.loads(ln.strip())
def ensure_open(): # 实例被回收时重新 fresh open
if (call("slide_get_info") or {}).get("slide_count", 0) > 1: return True
subprocess.run([sys.executable,"edsdk.py","call","open_file",
"file_path="+FID,"open_with_existing=false"], cwd=SKILL, capture_output=True)
time.sleep(2); return bool((call("slide_get_info") or {}).get("slide_count",0) > 1)
扫描:slide_get_info 拿 slide_count;逐页 slide_get_page_info,用 ^\s*\d+\s*/\s*\d+\s*$ 匹配页码框并记录 id/x/y/w/font_size/font_color。
执行(每页):旧框 slide_remove_shapes(shape_ids=[旧id]) → slide_add_text(x,y,w,h,text,font_name,font_color)(返回 shape_id)→ slide_set_text_property(shape_id, index=0, count=-1, font_size=10.5, ...)。
slide_set_shape_properties / 批量 shapes=[] 可用于改位置,但注意一次只能作用于一个 page_index,跨页无法批量。
保存:save_file(省略 file_path 覆盖原文件)。校验:close_file 后 open_file fresh,逐页重读比对(不要只看内存态)。
规划要点(决定好不好看)
- 分母:以
slide_count为准(如 86)。 - x / 宽度 / 字号 / 字体必须统一,否则一眼看出参差:推荐 x=870、w=76、h=14、微软雅黑 10.5pt。
- y 不要取绝对统一值。原稿页脚条本身可能有多种高度(实测 480/484/495/500/501pt 混用),统一 y 会让页码跳出页脚条。正确做法:优先取该页左下页脚标题(如 "WorkBuddy 企业智能办公实践")的 y;无标题则取页脚条垂直中心 - 6.5;再退化为默认 507。
- 深色页配色:若某页存在
x=0,y=0,w≈960,h≈540且 fill 为0B2545 / 1E3A5F / 1F4E79之类的全页形状,判为深色页,页码用浅色(如9FB0C8),否则用6B7280。 - 页码框段落对齐默认未显式设置(继承文本框默认左对齐),所以统一 x 即可对齐;若原框是居中/右对齐需另行确认。
踩坑
| 现象 | 处理 |
|---|---|
page_index out of range [0, 0) |
实例被回收,重新 open_file ... open_with_existing=false |
save_file 报 Export file is occupied |
目标被 WPS/PowerPoint 锁定(tasklist \| grep -i wpp)。改用 save_file file_path=<新路径> 另存,再尝试覆盖;覆盖前先 shutil.copyfile 备份原件 |
slide_add_text 传 10.5 报错 |
其 font_size 只收 integer;先用整数建,再 slide_set_text_property 设 10.5 |
| 改文本后样式没了 | slide_set_text / slide_find_replace_text 会重置 run 级样式(段落对齐保留),必须补 font_name / color / font_size |
| 试验残留 | 单页试验若走同一实例,会被后续 save_file 一起导出。试验后记得删除,或在最终校验里查重复框(同页页码框 count 必须 == 1) |
交付
present_files 呈现最终文件;若原文件被占用无法覆盖,明确告知用户「原件已备份为 xxx,关闭 WPS/PowerPoint 后可覆盖或用新文件」。