HOWTO · Python
Python-PPTX 庫
安裝 python-pptx,並使用 Python 建立 PowerPoint 簡報、將投影片文字擷取至文字檔,以及在投影片中加入圖片。
本頁內容
python-pptx 套件可讓你從 Python 程式碼建立與編輯 PowerPoint 檔案。本指南涵蓋套件安裝、建立含標題投影片的簡報、將投影片文字擷取到 .txt 檔案,以及在投影片上放置圖片。
python-pptx 可以做什麼
python-pptx 可讀寫 .pptx 檔案,也就是自 Office 2007 起 PowerPoint 所使用的簡報格式;它無法讀寫較舊的二進位 .ppt 格式。
常見用途包括從零開始產生簡報、依內建版面配置新增投影片、填入標題與內文預留位置、插入圖片、表格與圖表,以及開啟現有檔案修改其內容。由於一切都在 Python 中執行,這個函式庫很適合用於報表自動化與批次作業,而且不需要安裝 PowerPoint。
.pptx 檔案是由 XML 組件構成的 ZIP 封包,投影片文字儲存在 ppt/slides/slideN.xml 中。下面這個只使用標準函式庫的範例會組裝一個最小封包,並印出它在投影片上找到的文字,因此在任何能執行 Python 的環境中都能運作:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import tempfile
import zipfile
import xml.etree.ElementTree as ET
from pathlib import Path
work = Path(tempfile.mkdtemp())
deck = work / "hello.pptx"
parts = {
"[Content_Types].xml": (
'<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'
'<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>'
'<Default Extension="xml" ContentType="application/xml"/>'
'<Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/>'
'<Override PartName="/ppt/slides/slide1.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>'
"</Types>"
),
"_rels/.rels": (
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
'<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"/>'
"</Relationships>"
),
"ppt/presentation.xml": (
'<p:presentation xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" '
'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
'<p:sldIdLst><p:sldId id="256" r:id="rId1"/></p:sldIdLst></p:presentation>'
),
"ppt/_rels/presentation.xml.rels": (
'<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
'<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide1.xml"/>'
"</Relationships>"
),
"ppt/slides/slide1.xml": (
'<p:sld xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" '
'xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">'
'<p:cSld><p:spTree><p:sp><p:txBody><a:p><a:r><a:t>Hello DelftStack</a:t></a:r></a:p>'
"</p:txBody></p:sp></p:spTree></p:cSld></p:sld>"
),
}
with zipfile.ZipFile(deck, "w", zipfile.ZIP_DEFLATED) as zf:
for name, data in parts.items():
zf.writestr(name, data)
with zipfile.ZipFile(deck) as zf:
slide_xml = zf.read("ppt/slides/slide1.xml")
root = ET.fromstring(slide_xml)
for node in root.iter("{http://schemas.openxmlformats.org/drawingml/2006/main}t"):
print(node.text)
Hello DelftStack
python-pptx 將這些 XML 全部包裝在由簡報、投影片與圖案構成的簡單物件模型之後,本指南接下來都會使用這個模型。
安裝 python-pptx
在終端機或命令提示字元中執行 pip install python-pptx 即可安裝套件。散佈名稱是 python-pptx,但匯入名稱是 pptx,因此腳本會以 from pptx import Presentation 開頭。下面每段程式碼一開始都會進行一個小型的 find_spec 檢查:當 pptx 無法匯入時,腳本會印出提示並停止,而不是以 ModuleNotFoundError 失敗,因此無論在安裝前或安裝後執行這些程式碼都很安全。用來檢查本指南的環境並未安裝此套件,所以檢查之後的函式庫呼叫僅以未執行的參考程式碼形式呈現。
建立 PowerPoint 簡報
Presentation() 會從 python-pptx 隨附的範本建立簡報。prs.slide_layouts[0] 是標題投影片的版面配置,會為新投影片提供標題預留位置與副標題預留位置。下面的範例只填入標題;如果需要副標題,可以用相同方式透過 slide.placeholders[1].text 填入。save 會寫出 .pptx 檔案。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import importlib.util
import sys
if importlib.util.find_spec("pptx") is None:
print("python-pptx is not installed; run: pip install python-pptx")
sys.exit(0)
from pptx import Presentation
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[0])
slide.shapes.title.text = "PPT TITLE (PYTHON)"
prs.save("delft.pptx")
print("Saved delft.pptx")
套件安裝完成後,執行該腳本會將 delft.pptx 寫入目前工作目錄,並印出 Saved delft.pptx 作為確認(訊息文字依程式碼原樣以英文顯示)。產生的檔案可在 PowerPoint、LibreOffice Impress 或 Google 簡報中開啟,第一張投影片上會顯示該標題。
從 PowerPoint 檔案擷取文字
依序走訪 prs.slides 與 slide.shapes 即可觸及投影片上的每個元素。只有部分圖案帶有文字,因此先檢查 shape.has_text_frame 以跳過圖片及其他非文字項目。讀取 paragraph.text 會讓每個段落維持一行,輸出結果會比串接個別 run 更乾淨。如需在 Python 中進行其他文件轉換,請參閱如何在 Python 中將 Docx 轉換為 PDF。
該範例會在暫存資料夾中建立一個小型的來源檔案以保持自足;請改為將 src 指向你自己的 .pptx 檔案。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import importlib.util
import os
import sys
import tempfile
if importlib.util.find_spec("pptx") is None:
print("python-pptx is not installed; run: pip install python-pptx")
sys.exit(0)
from pptx import Presentation
work = tempfile.mkdtemp()
src = os.path.join(work, "demo.pptx")
out_path = os.path.join(work, "demo.txt")
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[0])
slide.shapes.title.text = "Quarterly results"
slide = prs.slides.add_slide(prs.slide_layouts[1])
slide.shapes.title.text = "Next steps"
slide.placeholders[1].text = "Ship the report"
prs.save(src)
doc = Presentation(src)
lines = []
for slide in doc.slides:
for shape in slide.shapes:
if not shape.has_text_frame:
continue
for paragraph in shape.text_frame.paragraphs:
if paragraph.text.strip():
lines.append(paragraph.text)
with open(out_path, "w", encoding="utf-8") as fh:
fh.write("\n".join(lines) + "\n")
print("\n".join(lines))
套件安裝完成後,腳本會印出 Quarterly results、Next steps 與 Ship the report(這些是範例檔案中的英文段落內容,依程式碼原樣輸出),並將相同的幾行寫入 demo.txt,每個段落一行。表格與圖表需要透過 shape.has_table 和 shape.has_chart 另行處理,因為它們的內容位於 text_frame 之外。
在投影片中加入圖片
slide.shapes.add_picture 接受圖片路徑,以及相對於投影片左上角的 left 與 top 距離。pptx.util 中的 Inches 輔助函式會將英寸轉換為此格式使用的 EMU 單位。傳入 width 或 height 可在維持長寬比的情況下縮放圖片,兩者都傳入則可指定精確尺寸。prs.slide_layouts[6] 是空白版面配置,當投影片只需要圖片時,它是乾淨的起點。
該範例會將一個微小的 PNG 解碼到暫存檔案以保持自足;請將 img_path 換成你自己的檔案,例如 logo.png。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
import base64
import importlib.util
import os
import sys
import tempfile
if importlib.util.find_spec("pptx") is None:
print("python-pptx is not installed; run: pip install python-pptx")
sys.exit(0)
from pptx import Presentation
from pptx.util import Inches
png = base64.b64decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==")
img_path = os.path.join(tempfile.mkdtemp(), "logo.png")
with open(img_path, "wb") as fh:
fh.write(png)
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6])
slide.shapes.add_picture(img_path, Inches(1), Inches(1), width=Inches(3))
prs.save("with_image.pptx")
print("Saved with_image.pptx")
套件安裝完成後,腳本會印出 Saved with_image.pptx,儲存的檔案中包含一張投影片,圖片錨定在距離上緣與左緣各一英寸的位置。使用完整尺寸照片時的典型結果如下所示:
同一個物件模型也涵蓋表格、圖表與其他圖案,因此這些模式可以延伸到大多數例行的投影片產生工作。