PPTX 创建、编辑和分析
一个 .pptx 文件是包含 XML 文件的 ZIP 归档文件。根据任务选择合适的方法:
| 任务 | 方法 |
|---|---|
| 创建新演示文稿 | 编写 pptxgenjs 脚本 — 请参阅下方的注意事项 |
| 编辑现有演示文稿,或基于模板构建 | 解压 → 编辑 ppt/slides/slideN.xml → 重新压缩 |
| 读取内容 | markitdown deck.pptx(每张幻灯片一个块,位于 <!-- Slide number: N --> 标记下);可视化网格:python scripts/thumbnail.py deck.pptx |
脚本
路径相对于此技能目录。其他内容均为纯 Python、node 或 shell 命令。
| 脚本 | 功能 |
|---|---|
scripts/thumbnail.py deck.pptx [前缀] | 每张幻灯片的带标签网格,用于选择模板布局。仅支持 .pptx 文件。传递 前缀 — 默认为 thumbnails,会覆盖同一目录下其他演示文稿的网格 |
scripts/add_slide.py unpacked/ slide2.xml [--after slideN.xml] | 复制一张幻灯片(或 slideLayoutN.xml),并处理所有包内簿记。也可直接操作 .pptx 文件,使用 -o out.pptx |
scripts/clean.py unpacked/ | 删除不再引用的幻灯片、媒体和关系文件。在 <p:sldIdLst> 最终确定后运行 |
scripts/office/validate.py deck.pptx [--original src.pptx] | 检查架构、关系、内容类型、图表和幻灯片;每个失败项均标明其修复方法。传递 --original 用于任何基于模板的演示文稿 — 它会以模板为基准进行架构检查,因此模板自身的 XSD 错误不会被视为您的问题 |
scripts/office/soffice.py --headless --convert-to pdf deck.pptx | LibreOffice 包装器 — 在此沙箱中直接使用 soffice 会挂起 |
使用 pptxgenjs 创建 — 注意事项
pptxgenjs 已预安装 — 不要先运行 npm install;直接编写脚本并使用 require('pptxgenjs')。仅当该 require 失败时:运行 npm install pptxgenjs。模型了解其 API;以下是易错点:
- 在添加幻灯片之前设置
pres.layout。 默认画布为LAYOUT_16x9= 10" × 5.625",而非 13.3 英寸宽。超出边缘的坐标会被写入,但不会被裁剪 — 形状只是不在幻灯片上。(LAYOUT_WIDE是 13.3" × 7.5"。) - 十六进制颜色:不要使用
#,不要使用 8 位数字。 使用color: "FF0000"。"#FF0000"和将 Alpha 值嵌入十六进制(如"00000020")都会损坏文件。对于透明度:在填充和图像上使用transparency: 0-100,在阴影上使用opacity: 0.0-1.0— 每个选项在另一处会被静默忽略。 - pptxgenjs 会就地修改选项对象(首次使用时将值转换为 EMU)。不要在两次
add*调用之间共享同一个shadow/选项对象 — 每次调用都构建一个新的对象。 - 阴影
offset必须 ≥ 0 — 负值会损坏文件。要向上投射阴影,请使用angle: 270配合正偏移。 letterSpacing会被静默忽略 — 实际选项是charSpacing。- 列表: 每个项目使用
bullet: true,不要使用字面•(会导致双项目符号)。在每个数组项目上设置breakLine: true,最后一个除外。使用paraSpaceAfter来分隔项目符号段落,不要使用lineSpacing(会导致巨大间距)。 - 每个输出文件使用一个
new pptxgen()实例 — 不要重复使用实例。 rectRadius仅在ROUNDED_RECTANGLE上有效,在RECTANGLE上无效。- 不支持渐变填充 — 请使用渐变图像作为背景。
- 文本框有内置的内边距 — 当文本需要与同一 x 位置的形状、线条或图标对齐时,请设置
margin: 0。 - 演讲者备注放在
slide.addNotes("...")中(纯文本,每张幻灯片一次),不要放在幻灯片上的文本框中。 - 保持图表原生。 对所有 PowerPoint 可以绘制的图表使用
addChart()(传递{type, data, options}数组用于组合图)。对于库未公开的 PowerPoint 原生功能(趋势线、误差线),请自行计算额外的系列或后处理生成的 OOXML — 不要退而使用渲染图像。只有 PowerPoint 没有原生形式的图表类型(桑基图、网络图、弦图)才作为图像插入。 - 默认图表渲染较为朴素 — 无标题、无数据标签、调色板过时。请设置
showTitle+title、showValue: true+dataLabelPosition、从您的调色板中选择chartColors: [...],并隐藏框架(catAxisLabelColor/valAxisLabelColor、valGridLine: { color, size }、catGridLine: { style: "none" }、对于单一系列设置showLegend: false)。 - 在堆叠条形图或柱状图上,
dataLabelPosition必须为ctr、inEnd或inBase。outEnd会损坏文件。 - 使用
secondaryValAxis/secondaryCatAxis的组合系列需要在图表选项上同时提供valAxes和catAxes,各两个条目。 没有它们,pptxgenjs 会写入从未声明的轴 ID,PowerPoint 会丢弃该图表并报告文件损坏。仅提供valAxes是不够的。 - 在
writeFile()之后,运行python scripts/office/validate.py deck.pptx。 它会报告上述两个图表缺陷以及 PowerPoint 拒绝的幻灯片 XML 缺陷,并标出每个问题的修复方法。请在生成器中修复它们,不要手动编辑打包后的 XML。 - 永远不要重新排序
<p:presentation>的子元素。 pptxgenjs 会在<p:sldIdLst>之后立即写入<p:notesMasterIdLst>,并将两个母版指向同一个主题部分。PowerPoint 可以正常读取 — 移动该元素后,同样的演示文稿将无法打开。 - 图标: 将
react-icons渲染为 SVG(ReactDOMServer.renderToStaticMarkup),使用sharp在 ≥256px 下栅格化,并通过addImage({ data: "image/png;base64," + buf.toString("base64") })插入 — 需要image/png;base64,前缀(react-icons、react、react-dom和sharp已预安装 — 仅当require失败时运行npm install react-icons react react-dom sharp)。
编辑现有演示文稿和模板
首先选择布局:python scripts/thumbnail.py template.pptx template-thumbs 会为每张幻灯片生成一个带标签的网格,并打印创建的文件 — template-thumbs.jpg,如果超过 12 张幻灯片则拆分为 template-thumbs-N.jpg。始终传递第二个参数,以演示文稿命名。 它默认为 thumbnails,因此同一目录下两个演示文稿的网格会静默覆盖彼此 — 第一个演示文稿的网格将消失(仅用于模板分析 — 可视化质量检查需要转换为图像中的全分辨率渲染;它只接受 .pptx,所以先将 .potx 复制为 .pptx 名称)。配合 markitdown 使用,将每个内容部分映射到模板幻灯片上,并变化布局 — 不要将每个部分都放在同一个标题和项目符号幻灯片上。
python3 -c "import sys,zipfile; zipfile.ZipFile(sys.argv[1]).extractall('unpacked')" deck.pptx
python scripts/add_slide.py unpacked/ slide2.xml --after slide2.xml # 复制一张幻灯片(或 slideLayoutN.xml);打印新幻灯片的路径
# 重新排序/删除幻灯片 = 编辑 ppt/presentation.xml 中的 <p:sldIdLst>
python scripts/clean.py unpacked/ # 删除后:移除孤立的幻灯片、媒体、关系文件
# 编辑 ppt/slides/slideN.xml 中的幻灯片内容
(cd unpacked && rm -f ../out.pptx && zip -Xr ../out.pptx .) # 在目录内部压缩;先 rm,否则已删除的部分会保留
python scripts/office/validate.py out.pptx --original deck.pptx
- 在进行任何幻灯片内容编辑之前,先完成所有结构性工作 — 添加、删除、重新排序。
add_slide.py会逐字复制幻灯片文件,因此编辑后复制会克隆已编辑的内容;而clean.py会删除<p:sldIdLst>中缺失的任何幻灯片,包括您刚刚编写的幻灯片。 - 永远不要手动复制幻灯片文件 —
add_slide.py会执行新幻灯片所需的所有注册操作,并报告创建的内容(Created ppt/slides/slide17.xml from slide2.xml)。它也可以直接操作文件:add_slide.py deck.pptx slide2.xml -o out.pptx— 请传递-o,否则它会直接修改输入的演示文稿。 复制的幻灯片仍然引用其来源的图表/SmartArt/嵌入对象部分,而不是克隆它们,因此编辑一张幻灯片的图表会改变另一张的图表。 - 如果使用
python-pptx,它有三件事做不到:复制幻灯片(其唯一入口点是add_slide(layout))、通过text_frame.text = "..."保留格式(这会将段落折叠为单个未设置样式的运行 — 请改为赋值run.text),或读取大多数模板艺术使用的 SVG/EMF(add_picture会引发UnidentifiedImageError)。 - 旧版
.ppt必须先转换:python scripts/office/soffice.py --headless --convert-to pptx file.ppt。.potx模板的解压和打包方式相同 — 在输出上保留.potx扩展名。 - 要重用模板图标或图像,请复制已包含它的幻灯片或布局。
填充模板时:
- 如果您编写 XML 转换脚本,请使用
defusedxml.minidom进行解析 — 通过xml.etree.ElementTree往返处理 OOXML 会重写命名空间前缀并损坏演示文稿。 - 模板位置 ≠ 源项目。 如果模板显示 4 个团队成员而您有 3 个,请删除第 4 个成员的整个组(图像 + 文本框),而不仅仅是其文本 — 然后在质量检查中检查是否有孤立的视觉效果。
- 每个列表项使用一个
<a:p>— 永远不要将项目连接到一个段落中。复制兄弟<a:pPr>以保留间距,并在标题、章节标题和内联标签(Status:、Owner:)的<a:rPr>上放置b="1"。 - 让项目符号从布局继承;仅在需要覆盖时添加
<a:buChar>、<a:buAutoNum>(编号)或<a:buNone>— 永远不要在文本中使用字面•。 - 带有前导或尾随空格的文本需要在其
<a:t>上使用xml:space="preserve"。
设计理念
不要创建无聊的幻灯片。 白色背景上的纯项目符号不会给任何人留下深刻印象。请考虑此列表中适用于每张幻灯片的想法。
开始之前
- 选择大胆、内容相关的配色方案:调色板应针对此主题进行设计。如果您的颜色应用到完全不同的演示文稿中仍然“有效”,则说明您没有做出足够具体的颜色选择。
- 主次分明而非均等:一种颜色应占主导地位(60-70% 的视觉重量),辅以 1-2 种支撑色调和一种锐利的强调色。永远不要给所有颜色相等的权重。
- 深色/浅色对比:标题和结论幻灯片使用深色背景,内容幻灯片使用浅色背景(“三明治”结构)。或者,为营造高级感,全程使用深色。
- 确定视觉主题:选择一个独特的元素并重复它 — 圆角图像框、彩色圆圈中的图标。在每张幻灯片上保持一致。不要使用色条或强调条纹作为主题(请参阅避免列表)。
配色方案
选择与主题匹配的颜色 — 不要默认使用通用蓝色。使用这些调色板作为灵感:
| 主题 | 主色 | 辅助色 | 强调色 |
|---|---|---|---|
| 午夜行政 | 1E2761 (海军蓝) | CADCFC (冰蓝) | FFFFFF (白色) |
| 森林与苔藓 | 2C5F2D (森林绿) | 97BC62 (苔藓绿) | F5F5F5 (奶油色) |
| 珊瑚活力 | F96167 (珊瑚红) | F9E795 (金色) | 2F3C7E (海军蓝) |
| 暖赤陶 | B85042 (赤陶色) | E7E8D1 (沙色) | A7BEAE (鼠尾草绿) |
| 海洋渐变 | 065A82 (深蓝) | 1C7293 (蓝绿色) | 21295C (午夜蓝) |
| 炭灰极简 | 36454F (炭灰色) | F2F2F2 (米白色) | 212121 (黑色) |
| 蓝绿色信任 | 028090 (蓝绿色) | 00A896 (海沫绿) | 02C39A (薄荷绿) |
| 浆果与奶油 | 6D2E46 (浆果红) | A26769 ( dusty rose) | ECE2D0 (奶油色) |
| 鼠尾草宁静 | 84B59F (鼠尾草绿) | 69A297 (桉树绿) | 50808E (石板蓝) |
| 樱桃大胆 | 990011 (樱桃红) | FCF6F5 (米白色) | 2F3C7E (海军蓝) |
每张幻灯片
每张幻灯片都需要一个视觉元素 — 图像、图表、图标或形状。纯文本幻灯片容易被遗忘。
布局选项:
- 两列(左文右图)
- 图标 + 文本行(彩色圆圈中的图标、粗体标题、下方描述)
- 2x2 或 2x3 网格(一侧为图像,另一侧为内容块网格)
- 半出血图像(全左或全右)并叠加内容
数据显示:
- 大号数据标注(大数字 60-72pt,下方小号标签)
- 对比列(之前/之后、优点/缺点、并排选项)
- 时间线或流程(带编号的步骤、箭头)
视觉美化:
- 在章节标题旁边的小彩色圆圈中的图标
- 关键统计信息或标语使用斜体强调文本
排版
您写入 .pptx 的字体名称由用户的 PowerPoint 呈现,而非此环境。 您的可视化质量检查通过 LibreOffice 进行渲染,它会替换自己没有的字体 — 对于某些字体,替换字体的宽度不同,因此您的质量检查预览可能显示实际演示文稿中不会出现的文本溢出(或合适)。为保持质量检查的可靠性:
- 安全字体(在质量检查中和 Office 中均能准确渲染宽度):Arial、Calibri、Cambria、Times New Roman、Courier New、Bookman Old Style、Century Schoolbook。将安全字体用于正文文本以及任何需要精确适配的内容。
- 零质量检查风险的个性化标题:将安全列表中的衬线标题(Cambria、Bookman Old Style、Century Schoolbook)与安全列表中的无衬线正文(Calibri 或 Arial)配对。您可以在不牺牲可靠溢出检查的情况下获得视觉对比。
- 如果用户要求使用安全列表之外的字体(例如 Georgia 或 Trebuchet MS):在用户要求的地方使用它,但为这些容器留出额外空间(约 10%),并且不要信任这些元素的质量检查文本适配 — 该字体的预览是近似的。如果用户未指定,正文文本首选安全列表字体。
- 质量检查不可靠的字体(替换字体宽度不同 — 溢出检查可能出错):Georgia、Trebuchet MS、Impact、Arial Black、Garamond、Consolas、Palatino Linotype。Calibri Light 的替换因环境而异;视为质量检查不可靠。可用于标题/强调并留出空间;不要信任这些元素的质量检查文本适配。
- 永远不要默认使用 Aptos — Office 2023 之后的默认字体在此处没有指标兼容的替换,并且在旧版 Office 安装中缺失,因此在两端都不可靠。
| 元素 | 字号 |
|---|---|
| 幻灯片标题 | 36-44pt 粗体 |
| 章节标题 | 20-24pt 粗体 |
| 正文文本 | 14-16pt |
| 说明文字 | 10-12pt 柔和 |
…
[已截断用于翻译]