Python使用python-pptx實(shí)現(xiàn)設(shè)置PPT頁面與文檔屬性
?老王的苦惱,很多做匯報(bào)的人都懂。
他是一家咨詢公司的項(xiàng)目經(jīng)理,每做完一個(gè)項(xiàng)目,要把二十幾頁的分析PPT、Excel圖表、Word總結(jié)拼成一份完整的匯報(bào)材料。最煩人的不是內(nèi)容,而是PPT頁面管理——有時(shí)候客戶要求把結(jié)論頁放到最前面,有時(shí)候要批量刪除某些頁的備注,有時(shí)候要在十幾份PPT的標(biāo)題欄統(tǒng)一加上項(xiàng)目編號(hào)。
每次手工搞一輪,至少兩個(gè)小時(shí)。
他問我:“能不能用代碼批量管理PPT的頁面?”
能,而且比你想象的簡單。今天的文章就聊聊用python-pptx怎么管好PPT的頁面和文檔本身,不涉及每一頁里頭的內(nèi)容怎么寫。
先搞清楚PPT的“骨架”長什么樣
在開始寫代碼之前,得先弄明白Python眼里一個(gè)PPT文件的結(jié)構(gòu)。
打個(gè)比方。一個(gè)PPT演示文稿就像一棟樓。樓有地基和框架(主題和母版),每一層是一個(gè)頁面(幻燈片),每一層的房間布局可能不一樣(布局),房間里放著家具和裝飾(文本框、圖片、表格)。
在python-pptx里,這個(gè)層次關(guān)系是這樣的:
- Presentation(演示文稿) :整棟樓,最外層的容器
- Slide(幻燈片) :每一層樓,也就是每一頁P(yáng)PT
- SlideLayout(幻燈片布局) :每層樓的房間格局模板
- SlideMaster(幻燈片母版) :整棟樓的統(tǒng)一設(shè)計(jì)規(guī)范
- Placeholder(占位符) :房間里預(yù)留的槽位,比如標(biāo)題該放哪、正文該放哪
理解了這層結(jié)構(gòu),后面所有操作就清晰多了。
創(chuàng)建和打開PPT:兩種入口
python-pptx有兩種方式拿到一個(gè)演示文稿對象:新建一個(gè)或者打開一個(gè)現(xiàn)有的。
新建一個(gè)空白PPT:
from pptx import Presentation
# 新建一個(gè)演示文稿(從內(nèi)置默認(rèn)模板創(chuàng)建)
prs = Presentation()
# 什么都不做,直接保存
prs.save("新建的PPT.pptx")
這個(gè)“默認(rèn)模板”其實(shí)就是一個(gè)沒有幻燈片的空PowerPoint文件,基于白色模板,寬高比是4:3。
打開現(xiàn)有的PPT:
prs = Presentation("項(xiàng)目周報(bào).pptx")
prs.save("項(xiàng)目周報(bào)_修改版.pptx")
注意一個(gè)細(xì)節(jié):如果你用同一個(gè)文件名打開和保存,Python會(huì)直接覆蓋原文件,沒有任何提示。如果你想保留原文件,記得換一個(gè)名字保存。
頁面的增刪改查:最核心的操作
拿到prs對象之后,真正干活的頁面管理就開始了。
先說最簡單也最常用的功能:判斷有多少頁、訪問特定頁面、找到某一頁的索引。
from pptx import Presentation
prs = Presentation("銷售匯報(bào).pptx")
# 一共有多少頁
print(f"總共有{len(prs.slides)}頁")
# 訪問第一頁(索引從0開始)
first_slide = prs.slides[0]
# 找到某一頁的索引位置
target_slide = prs.slides[3]
idx = prs.slides.index(target_slide)
print(f"目標(biāo)幻燈片在索引{idx}的位置")
# 遍歷所有頁面,打印每一頁的標(biāo)題
for i, slide in enumerate(prs.slides):
if slide.shapes.title:
print(f"第{i+1}頁標(biāo)題: {slide.shapes.title.text}")
else:
print(f"第{i+1}頁: 無標(biāo)題")
這里有個(gè)小坑。slide.shapes.title不一定能返回標(biāo)題。只有使用了帶標(biāo)題占位符布局的頁面才有shapes.title。如果你新建頁時(shí)選了“空白”布局(布局索引6),slide.shapes.title會(huì)返回None。
添加頁面:選對布局最重要
添加一頁P(yáng)PT不是隨便加的,你得告訴Python:這一頁用什么樣的布局。
# 查看當(dāng)前PPT有哪些可用的布局
for i, layout in enumerate(prs.slide_layouts):
print(f"布局索引 {i}: {layout.name}")
運(yùn)行這段代碼,你會(huì)看到類似這樣的輸出:
布局索引 0: Title Slide
布局索引 1: Title and Content
布局索引 2: Section Header
布局索引 3: Two Content
...
布局索引 6: Blank
不同的模板順序可能不一樣,你可以通過layout.name來確認(rèn)每個(gè)索引對應(yīng)什么布局。
選好布局之后,添加頁面就是一行代碼的事:
# 添加一頁"標(biāo)題+內(nèi)容"布局的幻燈片 slide_layout = prs.slide_layouts[1] # Title and Content slide = prs.slides.add_slide(slide_layout) # 往標(biāo)題占位符里寫內(nèi)容 slide.shapes.title.text = "三季度經(jīng)營分析" # 往內(nèi)容占位符里寫內(nèi)容(通常索引1是正文占位符) slide.placeholders[1].text = "營收同比增長15%\n利潤同比增長22%"
placeholders本質(zhì)上是一個(gè)類似字典的集合,它的“鍵”是占位符的idx值,而不是它在列表里的位置。這幾個(gè)內(nèi)置布局的占位符索引規(guī)律是:如果存在標(biāo)題占位符,它的idx永遠(yuǎn)是0;其他占位符從上到下、從左到右依次排列。
如果想讓PPT更通用,不依賴特定索引,可以這樣判斷:
for shape in slide.placeholders:
print(f"占位符索引: {shape.placeholder_format.idx}, 名稱: {shape.name}")
刪除頁面:官方不支持的偏方
python-pptx官方目前沒有直接提供刪除幻燈片的方法。按照官方文檔的說法,添加幻燈片是當(dāng)時(shí)唯一支持的操作,刪除和移動(dòng)還在開發(fā)計(jì)劃里。
但社區(qū)里有人找到了繞路的方法:直接操作底層的XML結(jié)構(gòu)。
from pptx import Presentation
prs = Presentation("待清理的PPT.pptx")
# 獲取所有幻燈片對象的列表
slides = list(prs.slides._sldIdLst)
# 刪除索引為2的幻燈片(第三頁)
prs.slides._sldIdLst.remove(slides[2])
prs.save("刪了一頁之后.pptx")
prs.slides._sldIdLst是整個(gè)PPT頁面列表的底層數(shù)據(jù)結(jié)構(gòu),直接操作它可以繞開官方API的限制。這種做法的優(yōu)點(diǎn)是簡單直接,缺點(diǎn)是不夠穩(wěn)定,文檔沒有保證這個(gè)內(nèi)部屬性會(huì)在未來的版本里保持不變。生產(chǎn)環(huán)境謹(jǐn)慎使用。
另一種更穩(wěn)妥但不那么靈活的做法是:新建一個(gè)PPT,只把你想要保留的頁面復(fù)制過去。
old_prs = Presentation("原始.pptx")
new_prs = Presentation()
# 只復(fù)制前3頁
for i in range(3):
old_slide = old_prs.slides[i]
new_slide = new_prs.slides.add_slide(old_prs.slide_layouts[0])
# 復(fù)制內(nèi)容的邏輯稍復(fù)雜,這里不再展開
new_prs.save("剪輯版.pptx")
復(fù)制頁面:手把手克隆一個(gè)完整的幻燈片
有些人可能已經(jīng)注意到,python-pptx沒有內(nèi)置的duplicate_slide方法。這是因?yàn)閺?fù)制一個(gè)頁面比看起來復(fù)雜得多——它涉及頁面上的所有形狀、圖表、圖片以及與它們關(guān)聯(lián)的關(guān)系。
一個(gè)可用的復(fù)制方案是這樣的:
from pptx import Presentation
from copy import deepcopy
def duplicate_slide(pres, source_index):
source = pres.slides[source_index]
# 使用空白布局作為新頁面的容器
blank_layout = pres.slide_layouts[6] # 布局6通常是"空白"
new_slide = pres.slides.add_slide(blank_layout)
# 復(fù)制原頁面上的所有形狀
for shape in source.shapes:
new_shape = deepcopy(shape.element)
new_slide.shapes._spTree.insert_element_before(new_shape, 'p:extLst')
return new_slide
prs = Presentation("示例.pptx")
duplicate_slide(prs, 0) # 復(fù)制第一頁
prs.save("復(fù)制了一頁之后.pptx")
這里的關(guān)鍵是用了deepcopy把原頁面上的形狀復(fù)制一份,然后插入到新頁面的形狀樹里。對于簡單的文本框,這個(gè)方法夠用。但如果原頁面里有圖表或圖片,可能需要額外處理它們對應(yīng)的二進(jìn)制數(shù)據(jù)。
重排頁面順序:同樣沒有官方支持
移動(dòng)頁面的位置和刪除頁面一樣,官方也沒有提供直接的方法。最直接的變通思路和刪除類似:新建一個(gè)PPT,按照你想要的順序重新添加頁面。
old_prs = Presentation("順序錯(cuò)亂的.pptx")
new_prs = Presentation()
# 假設(shè)想要的新順序是 [2, 3, 4, 0, 1]
order = [2, 3, 4, 0, 1]
for idx in order:
old_slide = old_prs.slides[idx]
new_layout = new_prs.slide_layouts[0] # 臨時(shí)占位布局
new_slide = new_prs.slides.add_slide(new_layout)
# 復(fù)制內(nèi)容的代碼......
如果你打算在生成階段就對順序有掌控,更好的做法是直接按想要的順序往新的PPT里添加頁面,而不是先生成再重排。
文檔屬性:給PPT加“身份證”
每個(gè)PPT文件都自帶一套元數(shù)據(jù),就像文件的身份證——作者是誰、標(biāo)題是什么、關(guān)鍵詞有哪些。這在文件管理和搜索引擎里很有用。
python-pptx通過core_properties提供了對這些屬性的讀寫支持。
prs = Presentation()
# 查看已有屬性
print(f"作者: {prs.core_properties.author}")
print(f"標(biāo)題: {prs.core_properties.title}")
# 修改屬性
prs.core_properties.title = "2026年Q2運(yùn)營分析報(bào)告"
prs.core_properties.author = "老王"
prs.core_properties.subject = "季度經(jīng)營數(shù)據(jù)與趨勢分析"
prs.core_properties.keywords = "運(yùn)營,報(bào)告,Q2"
prs.save("帶屬性的PPT.pptx")
你可以在Windows文件資源管理器里右鍵點(diǎn)擊文件→“屬性”→“詳細(xì)信息”里看到這些信息。
完整的屬性列表包括:title(標(biāo)題)、subject(主題)、author(作者)、keywords(關(guān)鍵詞)、category(類別)、comments(備注)、content_status(內(nèi)容狀態(tài))、revision(修訂號(hào))、version(版本)、identifier(標(biāo)識(shí)符)、language(語言)、last_modified_by(最后修改者)。不是每個(gè)都需要填,但設(shè)置title、author和keywords對文件歸檔會(huì)有幫助。
全局設(shè)置:頁面尺寸
有時(shí)候公司統(tǒng)一要求把PPT從標(biāo)準(zhǔn)4:3改成寬屏16:9。手工改幾十個(gè)PPT顯然不現(xiàn)實(shí),用一行代碼就能解決:
from pptx.util import Inches
prs = Presentation()
# 設(shè)置頁面為寬屏16:9(寬13.33英寸,高7.5英寸)
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
prs.save("寬屏版.pptx")
slide_width和slide_height的單位是EMU,但Inches和Cm這兩個(gè)工具函數(shù)會(huì)自動(dòng)幫你轉(zhuǎn)換。
頁眉頁腳與幻燈片編號(hào)
幻燈片編號(hào)、頁腳文字、日期這三個(gè)東西在PPT里統(tǒng)稱為“頁腳”,它們的處理方式和普通占位符有些區(qū)別。
如果你想在生成的PPT里顯示幻燈片編號(hào),不能在代碼層面直接“開啟”——這屬于母版層級的設(shè)置。正確做法是:先手工做一個(gè)帶編號(hào)的母版(在PowerPoint里打開母版視圖,通過“插入→幻燈片編號(hào)”菜單在母版上插入編號(hào)占位符),保存為模板文件,然后在代碼里用這個(gè)模板創(chuàng)建新PPT。
簡單說,就是“母版手工配,內(nèi)容代碼填”。如果你的項(xiàng)目中不需要編號(hào),這個(gè)步驟可以跳過。
信息提?。鹤x取PPT原本的頁面清單
有時(shí)候你需要分析一個(gè)PPT的結(jié)構(gòu),比如看看它有多少頁、每一頁用的是什么布局、里面有什么占位符。
from pptx import Presentation
prs = Presentation("待分析的PPT.pptx")
for idx, slide in enumerate(prs.slides):
print(f"\n=== 幻燈片 {idx+1} ===")
print(f"使用的布局: {slide.slide_layout.name}")
# 統(tǒng)計(jì)頁面上的形狀類型
shape_types = {}
for shape in slide.shapes:
shape_type = type(shape).__name__
shape_types[shape_type] = shape_types.get(shape_type, 0) + 1
print(f"形狀統(tǒng)計(jì): {shape_types}")
這個(gè)腳本跑完,你能快速了解這份PPT的構(gòu)成——是圖片多還是文字多,有沒有表格,結(jié)構(gòu)是否合理。
避坑指南
前面提到的._sldIdLst是內(nèi)部數(shù)據(jù)結(jié)構(gòu),可能因庫的版本更新而變化。如果追求穩(wěn)定,建議用新建PPT并按順序添加頁面的替代方案。
用slide.placeholders[idx]訪問占位符時(shí),idx是占位符的索引值,不是它在列表里的位置編號(hào)。提前打印一遍所有占位符的idx值可以避免KeyError。
修改現(xiàn)有PPT時(shí),如果直接用prs.save("原文件名.pptx")覆蓋保存,原有的備份就被抹掉了。建議養(yǎng)成先另存為的習(xí)慣。
老王把這些整理成腳本之后,每周的匯報(bào)材料整理從兩小時(shí)縮短到了兩分鐘。他說了一句挺實(shí)在的話:“代碼不是要解決多難的問題,是把那80%的重復(fù)勞動(dòng)一次性寫死。”
在我看來,手動(dòng)整理PPT就像每年在院子里拔草,拔完還會(huì)長。用代碼管PPT,就像給院子鋪上水泥——雜草的根被壓在底下,長出來了也能一鏟子鏟完。
?到此這篇關(guān)于Python使用python-pptx實(shí)現(xiàn)設(shè)置PPT頁面與文檔屬性的文章就介紹到這了,更多相關(guān)Python設(shè)置PPT頁面與文檔屬性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 使用Python管理PPT頁面與文檔屬性
- Python使用pptx實(shí)現(xiàn)復(fù)制頁面到其他PPT中
- python實(shí)現(xiàn)向ppt文件里插入新幻燈片頁面的方法
- Python實(shí)現(xiàn)PPT創(chuàng)建文本框并設(shè)置格式的完整步驟
- Python實(shí)現(xiàn)從PPT提取圖片和文本
- 使用Python實(shí)現(xiàn)批量為PPT添加動(dòng)畫
- Python使用python-pptx實(shí)現(xiàn)自動(dòng)化制作PPT
- Python實(shí)現(xiàn)解構(gòu)PPT并提取文本、圖片和表格
相關(guān)文章
python實(shí)現(xiàn)獲取當(dāng)前設(shè)備的地點(diǎn)位置
這篇文章主要介紹了python實(shí)現(xiàn)獲取當(dāng)前設(shè)備的地點(diǎn)位置,電腦如何獲取當(dāng)前所處的地理位置?它不會(huì)像我們一樣對地理位置有感性的認(rèn)知,它只認(rèn)識(shí)數(shù)據(jù),簡言之,電腦可以通過獲取當(dāng)前連接的公網(wǎng)IP,反推所處的位置環(huán)境,需要的朋友可以參考一下2022-03-03
詳解python 3.6 安裝json 模塊(simplejson)
這篇文章主要介紹了python 3.6 安裝json 模塊(simplejson),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
Python面向?qū)ο筮M(jìn)階學(xué)習(xí)
在本文里我們整理了關(guān)于Python面向?qū)ο蟮倪M(jìn)階學(xué)習(xí)知識(shí)點(diǎn)以及學(xué)習(xí)路線等內(nèi)容,有興趣的朋友們學(xué)習(xí)下。2019-05-05
Pytorch數(shù)據(jù)讀取與預(yù)處理該如何實(shí)現(xiàn)
這篇文章主要介紹了Pytorch數(shù)據(jù)讀取與預(yù)處理該如何實(shí)現(xiàn),幫助大家更好的理解和學(xué)習(xí)使用Pytorch,感興趣的朋友可以了解下2021-03-03
Python進(jìn)階技巧之利用break和哈希算法優(yōu)化數(shù)據(jù)庫批量操作
這篇文章主要為大家詳細(xì)介紹了Python如何利用break和哈希算法優(yōu)化數(shù)據(jù)庫批量操作,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2026-01-01

