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),並處理所有套件書籤。也可以直接用 -o out.pptx 指定 .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 .) # 從目錄**內部**進行壓縮;先刪除,否則已刪除的部分會留存
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-ppttx,請注意它有三個無法做到的事情:複製投影片(唯一的進入點是add_slide(layout))、透過text_frame.text = "..."保留格式(這會將段落摺疊為單一無樣式的 run — 請改用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 (塵玫瑰) | 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 低調 |
…
[原文已截斷,僅供翻譯]