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 [prefix] | 每张幻灯片的带标签网格,用于挑选模板布局。仅限 .pptx。传递 prefix — 默认为 thumbnails,这将会覆盖同一目录中任何其他演示文稿的网格 |
scripts/add_slide.py unpacked/ slide2.xml [--after slideN.xml] | 复制幻灯片(或 slideLayoutN.xml)并完成所有包注册。也可以直接接受 .pptx 文件并附带 -o out.pptx |
scripts/clean.py unpacked/ | 删除不再被引用的幻灯片、媒体和 rels 文件。在 <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/options 对象 — 每次都创建一个新对象。 - 阴影
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,因此同一个目录中两个演示文稿的缩略图会静默地互相覆盖网格 — 第一个演示文稿的网格会直接消失(模板分析只需要 — 视觉 QA 需要转换为图片中的全分辨率渲染;它只接受 .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/ # 删除后:移除孤立的幻灯片、媒体、rels
# 在 ppt/slides/slideN.xml 中编辑幻灯片内容
(cd unpacked && rm -f ../out.pptx && zip -Xr ../out.pptx .) # 在目录内压缩;先删除,否则已删除的部分会保留
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 名成员的整个组(图片 + 文本框),而不仅仅是其文本 — 然后在 QA 中检查是否有孤立的视觉效果。
- 每个列表项一个
<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 (灰玫瑰) | ECE2D0 (奶油色) |
| 鼠尾草宁静 | 84B59F (鼠尾草绿) | 69A297 (桉树绿) | 50808E (石板蓝) |
| 樱桃大胆 | 990011 (樱桃红) | FCF6F5 (米白) | 2F3C7E (深蓝) |
每张幻灯片
每张幻灯片都需要一个视觉元素 — 图片、图表、图标或形状。纯文本的幻灯片容易被遗忘。
布局选项:
- 两栏(文字在左,插图在右)
- 图标 + 文字行(彩色圆圈中的图标,粗体标题,下方描述)
- 2x2 或 2x3 网格(一侧是图片,另一侧是内容块网格)
- 半出血图片(整张幻灯片的左侧或右侧)覆盖内容
数据显示:
- 大号数字标注(大数字 60-72pt,下方小标签)
- 比较栏(之前/之后、优点/缺点、并排选项)
- 时间线或流程(编号步骤、箭头)
视觉润色:
- 节标题旁边的小彩色圆圈中的图标
- 用于关键统计数据或标语的重点斜体文本
排版
您写入 .pptx 的字体名称由用户的 PowerPoint 渲染,而不是由这个环境渲染。 您的视觉 QA 通过 LibreOffice 渲染,它会替换不存在的字体 — 对于某些字体,替换后的字体具有不同的宽度,因此您的 QA 预览可能会显示文本溢出(或正好适合)而实际演示文稿不会有问题。为了使您的 QA 可信:
- 安全字体(在 QA 中宽度真实 并且 随 Office 一起提供):Arial、Calibri、Cambria、Times New Roman、Courier New、Bookman Old Style、Century Schoolbook。将其用于正文文本以及任何需要适配的内容。
- 零 QA 风险的有特色标题:将安全列表衬线标题(Cambria、Bookman Old Style、Century Schoolbook)与安全列表无衬线正文(Calibri 或 Arial)配对。您可以在不牺牲可靠的溢出检查的情况下获得视觉对比。
- 如果用户要求使用安全列表之外的字体(例如 Georgia 或 Trebuchet MS):在用户要求的地方使用它,但将这些容器的大小设置得稍大一些(约 10%),并且不要信任这些元素上的 QA 文本适配 — 该字体的预览是近似的。如果用户没有指定,正文文本优先使用安全列表字体。
- QA 不可靠字体(替换字体具有不同的宽度 — 溢出检查可能错误):Georgia、Trebuchet MS、Impact、Arial Black、Garamond、Consolas、Palatino Linotype。Calibri Light 的替换因环境而异;将其视为 QA 不可靠字体。适用于带松量的标题/强调;不要信任这些字体的 QA 文本适配。
- 永远不要默认使用 Aptos — Office 2023 之后的默认字体在此处没有指标兼容的替换字体 并且 在旧版 Office 安装中缺失,因此在两端都不可靠。
| 元素 | 大小 |
|---|---|
| 幻灯片标题 | 36-44pt 粗体 |
| 节标题 | 20-24pt 粗体 |
| 正文文本 | 14-16pt |
| 说明文字 | 10-12pt 柔和 |
…
[翻译截断]