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

