Python處理PPT文件的實(shí)用知識(shí)點(diǎn)總結(jié)
前言
和Word、Excel承載數(shù)據(jù)的能力相比,PPT的應(yīng)用重點(diǎn)在于表演。
比如一場(chǎng)發(fā)布會(huì)、一場(chǎng)演說(shuō)、一次產(chǎn)品展示、一次客戶(hù)溝通……
正常情況下,用PowerPoint等軟件制作PPT是明智的選擇,簡(jiǎn)單實(shí)用。
但如果需要批量或者自動(dòng)化處理PPT文件時(shí),用Python就能節(jié)省很多時(shí)間。
比如:
- 用PPT批量生成一些發(fā)布會(huì)風(fēng)格的圖片
- 從大量PPT中提取表格數(shù)據(jù)
- 用PPT批量制作簡(jiǎn)單動(dòng)畫(huà)
處理PPT的Python庫(kù),主要有兩類(lèi):
pywin32,調(diào)用操作系統(tǒng)上已裝好的PPT軟件。python-pptx,根據(jù)OpenXML規(guī)范解析XML文件。
日常處理推薦使用python-pptx模塊,它基于PIL處理圖片,基于xlsxwriter處理圖表。
但如果需要批量轉(zhuǎn)換PPT文件格式,如導(dǎo)出成PDF,那就得用pywin32,而且只能在Windows操作系統(tǒng)上操作。
本文主要介紹python-pptx用法,模塊安裝:pip install python-pptx。
注意:python-pptx暫時(shí)還不支持SmartArt和動(dòng)畫(huà)。如果需要批量生成,就得自己操作XML文件中對(duì)應(yīng)內(nèi)容。
基本使用
PPT中基本元素包括:
- slide(幻燈片):一個(gè)PPT由一系列slide構(gòu)成。
- slide_master(幻燈片母版):母版可定義主題樣式基準(zhǔn)。
- slide_layouts(模版):創(chuàng)建幻燈片時(shí)可選擇的模版。
- shape(形狀):包含一切可視元素,通過(guò)slide.shapes可訪(fǎng)問(wèn)slide內(nèi)元素。
- placeholder(占位符):在模板中占據(jù)位置,如圖片、文字等。
- paragraph(段落):文本段,可以直接設(shè)置整段文本樣式。
- text(文本):段落內(nèi)的文本,通過(guò)paragraph.add_run()生成。
import pathlib
from pptx import Presentation
from pptx.enum.dml import MSO_THEME_COLOR
from pptx.util import Inches, Pt
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/005ppt')
out_path = path.joinpath('005ppt_basic.pptx')
prs = Presentation()
# 查看所有布局
for lo in prs.slide_layouts:
print(lo.name)
# 創(chuàng)建標(biāo)題頁(yè)
title_slide_layout = prs.slide_layouts[0]
print(w, h, lo, ma)
slide = prs.slides.add_slide(title_slide_layout)
title = slide.shapes.title
subtitle = slide.placeholders[1]
title.text = '只差一個(gè)程序員了'
subtitle.text = '程一初'
# 設(shè)置背景色
fill = slide.shapes[0].fill
fill.solid()
fill.fore_color.theme_color = MSO_THEME_COLOR.ACCENT_1
fill.fore_color.brightness = -0.25
# 創(chuàng)建第一頁(yè)內(nèi)容
bullet_slide_layout = prs.slide_layouts[1]
slide = prs.slides.add_slide(bullet_slide_layout)
shapes = slide.shapes
title_shape = shapes.title
body_shape = shapes.placeholders[1]
title_shape.text = 'Python1024'
tf = body_shape.text_frame
tf.text = '第一級(jí)內(nèi)容'
p = tf.add_paragraph()
p.text = '第一級(jí)段落內(nèi)容'
p.level = 1
p = tf.add_paragraph()
p.text = '第二級(jí)段落內(nèi)容'
p.level = 2
run = p.add_run()
# 與`python-docx`里的用法類(lèi)似,但內(nèi)容設(shè)置在`text`中
run.text = '自定義字體'
run.font.name = '微軟雅黑'
run.font.size = Pt(25)
run.font.bold = True
print(tf.paragraphs[0].text)
# 從一個(gè)空白頁(yè)開(kāi)始創(chuàng)建內(nèi)容
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)
left = top = width = height = Inches(1)
txt_box = slide.shapes.add_textbox(left, top, width, height)
tf = txt_box.text_frame
tf.text = '文本框內(nèi)容'
p = tf.add_paragraph()
p.text = '文本框內(nèi)增加一個(gè)粗體段落'
p.font.bold = True
p = tf.add_paragraph()
p.text = '文本框內(nèi)增加一個(gè)大字體段落'
p.font.size = Pt(40)
prs.save(out_path)
圖片和圖形
PPT中圖相關(guān)元素有3類(lèi):
- picture:圖像,單位是Inch
- autoshape:形狀,如流程圖
- chart:圖表,如直方圖、餅圖
生成流程圖
import pathlib
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.shapes import MSO_SHAPE
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/005ppt')
out_path = path.joinpath('005ppt_image.pptx')
img_path = path.joinpath('image.jpg')
prs = Presentation()
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)
# 增加兩張圖片,一大一小
left = top = Inches(1)
pic = slide.shapes.add_picture(str(img_path), left, top)
left = Inches(6)
height = Inches(3)
pic = slide.shapes.add_picture(str(img_path), left, top, height=height)
# 增加一個(gè)AutoShape流程圖
title_only_slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(title_only_slide_layout)
shapes = slide.shapes
shapes.title.text = '流程圖'
left = Inches(0.93) # 0.93" centers this overall set of shapes
top = Inches(3.0)
width = Inches(1.75)
height = Inches(1.0)
shape = shapes.add_shape(MSO_SHAPE.PENTAGON, left, top, width, height)
shape.text = '第一步'
left = left + width - Inches(0.4)
# 第一個(gè)形狀左邊平,第二個(gè)開(kāi)始,左邊有尖角,需要更長(zhǎng)
width = Inches(2.0)
for n in range(2, 6):
shape = shapes.add_shape(MSO_SHAPE.CHEVRON, left, top, width, height)
shape.text = f'第{n}步'
left = left + width - Inches(0.4)
prs.save(out_path)
生成圖表
import pathlib
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_TICK_MARK, XL_LABEL_POSITION, XL_LEGEND_POSITION
from pptx.dml.color import RGBColor
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/005ppt')
out_path = path.joinpath('005ppt_chart.pptx')
prs = Presentation()
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)
# 增加一個(gè)圖表
chart_data = CategoryChartData()
chart_data.categories = ['A銷(xiāo)售額', 'B銷(xiāo)售額', 'C銷(xiāo)售額']
chart_data.add_series('Q1銷(xiāo)售', (100, 120, 200))
chart_data.add_series('Q2銷(xiāo)售', (120, 150, 180))
chart_data.add_series('Q3銷(xiāo)售', (150, 180, 120))
chart_data.add_series('Q4銷(xiāo)售', (130, 210, 150))
x, y, cx, cy = Inches(2), Inches(2), Inches(6), Inches(4)
chart = slide.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED, x, y, cx, cy, chart_data
).chart
# 設(shè)置圖表的軸信息
category_axis = chart.category_axis
category_axis.has_major_gridlines = True
category_axis.minor_tick_mark = XL_TICK_MARK.OUTSIDE
category_axis.tick_labels.font.italic = True
category_axis.tick_labels.font.size = Pt(24)
plot = chart.plots[0] # 用Plot對(duì)象訪(fǎng)問(wèn)標(biāo)簽
plot.has_data_labels = True
data_labels = plot.data_labels
data_labels.font.size = Pt(13)
data_labels.font.color.rgb = RGBColor(0x0A, 0x42, 0x80)
data_labels.position = XL_LABEL_POSITION.INSIDE_END
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.RIGHT
chart.legend.include_in_layout = False
# 增加一個(gè)餅圖
slide = prs.slides.add_slide(blank_slide_layout)
chart_data = CategoryChartData()
chart_data.categories = ['A銷(xiāo)售額', 'B銷(xiāo)售額', 'C銷(xiāo)售額']
chart_data.add_series('年度銷(xiāo)售比', (0.276, 0.365, 0.359))
chart = slide.shapes.add_chart(
XL_CHART_TYPE.PIE, x, y, cx, cy, chart_data
).chart
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.BOTTOM
chart.legend.include_in_layout = False
chart.plots[0].has_data_labels = True
data_labels = chart.plots[0].data_labels
data_labels.number_format = '0%'
data_labels.position = XL_LABEL_POSITION.OUTSIDE_END
prs.save(out_path)
注意,關(guān)于圖形類(lèi)的處理,python-pptx模塊暫不支持下面兩種場(chǎng)景:
SmartArt,微軟并沒(méi)有公開(kāi)發(fā)布過(guò)其標(biāo)準(zhǔn)格式,目前只有PowerPoint軟件具備這個(gè)功能。- PPT文件按頁(yè)導(dǎo)出成圖片,這也是PowerPoint軟件功能,在Windows上可以借助
win32com等模塊調(diào)用PPT軟件功能實(shí)現(xiàn)。
生成數(shù)據(jù)表格
PPT中也可以插入表格,只不過(guò)表格功能非常有限,僅用于展示。
在自動(dòng)生成PPT時(shí),有時(shí)候需要把外部數(shù)據(jù)復(fù)制到PPT內(nèi),可以讀取數(shù)據(jù)后在PPT中插入表格。
比如:
import pathlib
from pptx import Presentation
from pptx.util import Inches
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/005ppt')
out_path = path.joinpath('005ppt_table.pptx')
prs = Presentation()
title_only_slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(title_only_slide_layout)
shapes = slide.shapes
shapes.title.text = '表格數(shù)據(jù)'
rows, cols = 5, 4
left = top = Inches(2.0)
width = Inches(6.0)
height = Inches(0.8)
table = shapes.add_table(rows, cols, left, top, width, height).table
data = [
('季度', 'A銷(xiāo)售', 'B銷(xiāo)售', 'C銷(xiāo)售'), # 表頭
('Q1', 100, 120, 200),
('Q2', 120, 150, 180),
('Q3', 150, 180, 120),
('Q4', 130, 210, 150),
]
for col in table.columns:
col.width = Inches(1.6)
table.columns[0].width = Inches(1.0)
for i, d in enumerate(data):
for j in range(4):
table.cell(i, j).text = str(data[i][j])
prs.save(out_path)
導(dǎo)出素材和數(shù)據(jù)
導(dǎo)出圖片和幻燈片備注
之前說(shuō)過(guò),想提取docx、xlsx、pptx文件里的圖片素材,可以先把文件解壓縮,然后到對(duì)應(yīng)目錄查看圖片。其中pptx文件解壓后,圖片在ppt/media文件夾內(nèi)。
當(dāng)然,也可以通過(guò)Python自動(dòng)導(dǎo)出。
import pathlib
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.shapes import MSO_SHAPE_TYPE
# 借用openpyxl的單位轉(zhuǎn)換
from openpyxl.utils.units import EMU_to_pixels as e2p
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/005ppt')
img_out_path = path.joinpath('005ppt_out_images')
txt_out_path = path.joinpath('005ppt_notes.txt')
in_path = path.joinpath('input_covid19.pptx')
prs = Presentation(in_path)
# EMU單位,1 Pixel = 9525 EMU
w, h = prs.slide_width, prs.slide_height
print(f'總共 {len(prs.slides)} 頁(yè),頁(yè)寬 {e2p(w)} px,頁(yè)高 {e2p(h)} px')
cnt_img, txt_list = 0, []
for i, slide in enumerate(prs.slides):
# 提取notes
notes_slide = slide.notes_slide
text_frame = notes_slide.notes_text_frame
txt_list.append(f'第 {i} 頁(yè):')
txt_list.append(text_frame.text)
# 提取圖片
for s in slide.shapes:
if s.shape_type == MSO_SHAPE_TYPE.PICTURE:
img = s.image
cnt_img += 1
ext = img.content_type.split('/')[1]
f_out_path = img_out_path.joinpath(f'{cnt_img}.{ext}')
with open(f_out_path, 'wb') as f:
f.write(img.blob)
print(f'總導(dǎo)出 {cnt_img} 張圖片.')
with open(txt_out_path, 'w') as txt_fout:
txt_fout.write('\n'.join(txt_list))
導(dǎo)出表格和及圖表中的數(shù)據(jù)
從上面導(dǎo)出圖片的過(guò)程可以看到,想要導(dǎo)出一個(gè)元素,關(guān)鍵是識(shí)別出它的類(lèi)型。
所以,導(dǎo)出表格和圖表的關(guān)鍵在于:識(shí)別出table和chart。
另外,有2個(gè)注意點(diǎn):
table的數(shù)據(jù)可以直接獲取,但注意python-pptx中表格索引從0開(kāi)始(openpyxl從1開(kāi)始)chart的數(shù)據(jù)在其內(nèi)部,需要通過(guò)plots.categories提取
import pathlib
from pptx import Presentation
from pptx.chart.data import CategoryChartData
from pptx.util import Inches, Pt
from pptx.enum.shapes import MSO_SHAPE_TYPE
from openpyxl.utils.units import EMU_to_pixels as e2p
from openpyxl import Workbook
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/005ppt')
table_out_path = path.joinpath('005ppt_out_tables.xlsx')
chart_data_out_path = path.joinpath('005ppt_out_chart_data.xlsx')
chart_out_path = path.joinpath('005ppt_out_charts')
in_path = path.joinpath('input_table.pptx')
prs = Presentation(in_path)
# EMU單位,1 Pixel = 9525 EMU
w, h = prs.slide_width, prs.slide_height
print(f'總共 {len(prs.slides)} 頁(yè),頁(yè)寬 {e2p(w)} px,頁(yè)高 {e2p(h)} px')
cnt_tables, cnt_charts = 0, 0
xlsx_wb = Workbook()
chart_wb = Workbook()
for i, slide in enumerate(prs.slides, start=1):
for j, s in enumerate(slide.shapes, start=1):
if s.shape_type == MSO_SHAPE_TYPE.TABLE and s.has_table:
cnt_tables += 1
tbl = s.table
cnt_row, cnt_col = len(tbl.rows), len(tbl.columns)
print(f'增加表格 {cnt_tables}: {cnt_row} x {cnt_col}')
ws = xlsx_wb.create_sheet(f'{cnt_tables}_page_{i}')
for r in range(cnt_row):
for c in range(cnt_col):
cell = tbl.cell(r,c)
text_runs = []
for paragraph in cell.text_frame.paragraphs:
for run in paragraph.runs:
text_runs.append(run.text)
ws.cell(row=r+1, column=c+1, value=''.join(text_runs))
elif s.shape_type == MSO_SHAPE_TYPE.CHART:
chart = s.chart
cnt_charts += 1
# 導(dǎo)出Chart的數(shù)據(jù)到表格
data = chart.series
# for plot in chart.plots:
# cat = list(plot.categories)
cat = list(chart.plots[0].categories) # 假設(shè)1個(gè)圖表
if len(data) > 0:
ws = chart_wb.create_sheet(f'{cnt_charts}_page_{i}')
print(f'增加Chart數(shù)據(jù) {cnt_charts}: {len(data)}行, {len(cat)} 列')
cat = ['標(biāo)簽'] + cat
ws.append(cat)
for d in data:
values = [d.name] + list(d.values)
ws.append(values)
xlsx_wb.save(table_out_path)
chart_wb.save(chart_data_out_path)
總結(jié)
本文重點(diǎn)介紹了python-pptx的使用方法,包括基本文件讀寫(xiě)、圖形圖像處理,以及表格圖表內(nèi)部數(shù)據(jù)的抽取等。
雖然PPT能裝載的數(shù)據(jù)有限,但它的表達(dá)能力豐富,關(guān)鍵是看怎樣應(yīng)用。不同的配色、布局、形狀、內(nèi)容,會(huì)產(chǎn)生完全不同的效果。
最后,可以嘗試下用PPT制作海報(bào)卡片,在PPT中批量生成slide是件容易的事,再打開(kāi)軟件導(dǎo)出圖片即可。比如把豆瓣上的高分電影,隨機(jī)配上金句文案:


順便再生成一個(gè)電影評(píng)分榜。

到此這篇關(guān)于Python處理PPT文件的文章就介紹到這了,更多相關(guān)Python處理PPT文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python偽代碼分析點(diǎn)贊器實(shí)現(xiàn)原理及代碼
這篇文章主要介紹了Python偽代碼分析點(diǎn)贊器實(shí)現(xiàn)原理,本次點(diǎn)贊?rùn)C(jī)器人,主要面向電腦上的 Web 站點(diǎn),不涉及 APP 端,需要的朋友可以參考下2022-04-04
django連接oracle時(shí)setting 配置方法
今天小編就為大家分享一篇django連接oracle時(shí)setting 配置方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08
Python爬蟲(chóng)必備之XPath解析庫(kù)
今天給大家?guī)?lái)的是Python爬蟲(chóng)的相關(guān)知識(shí),文章圍繞著XPath解析庫(kù)展開(kāi),文中有非常詳細(xì)的代碼示例及介紹,需要的朋友可以參考下2021-06-06
淺談Scrapy框架普通反爬蟲(chóng)機(jī)制的應(yīng)對(duì)策略
這篇文章主要介紹了淺談Scrapy框架普通反爬蟲(chóng)機(jī)制的應(yīng)對(duì)策略,具有一定借鑒價(jià)值,需要的朋友可以參考下2017-12-12
教你使用Sublime text3搭建Python開(kāi)發(fā)環(huán)境及常用插件安裝另分享Sublime text3最新激活注冊(cè)碼
這篇文章主要介紹了使用Sublime text 3搭建Python開(kāi)發(fā)環(huán)境及常用插件安裝,并提供了最新Sublime text 3激活注冊(cè)碼需要的朋友可以參考下2020-11-11
對(duì)Python中內(nèi)置異常層次結(jié)構(gòu)詳解
今天小編就為大家分享一篇對(duì)Python中內(nèi)置異常層次結(jié)構(gòu)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10

