自动化报告先从python-pptx开始
其他系列:
- 自动化报告的前奏|使用python-pptx操作PPT(一)
- 自动化报告pptx-python|如何将pandas的表格写入PPTX(二)
- 自动化报告pptx-python|高效通过PPT模版制造报告(三)
- 自动化报告pptx-python|pptx 分析报告的工具包:reportgen(四)
1 python-pptx的基础属性
1.1 新建幻灯片
1.1.1 幻灯片布局的样式
幻灯片布局的样式( slide_layouts ):
1.1.2 修改pptx模版大小
from pptx.util import Cm
prs = Presentation()
prs.slide_width = Cm(33.85)
prs.slide_height = Cm(19.02)
1.1.3 指定模版生成
可以先自定义一个指定了宽高的空白页PPT模板,创建Presentation对象时引用它,后续创建的幻灯片就能继承到对应的宽高大小
prs = Presentation("G:/simple_ppt/test/template.pptx")
1.1.4 创建幻灯片背景
可以通过slide的background来指定纯色背景
bg = slide.background
bg.fill.solid()
bg.fill.fore_color.rgb = RGBColor(219, 238, 244)
python-pptx库并没有直接提供设置图片作为幻灯片背景的方法,但可以通过将图片设置为铺满整个幻灯片来达到同样的效果
img_path = "G:/bg_image.png"
slide.shapes.add_picture(img_path, Cm(0), Cm(0), width=prs.slide_width, height=prs.slide_height)
slide_width和slide_height获取的分别是整张幻灯片的宽和高
这里要注意图片的层级问题,由于没有提供设置图片层级的方法,所以作为背景的图片应该放在构建幻灯片的第一位
纯色背景效果
1.1.5 创建幻灯片备注信息
幻灯片底部的备注信息,在分屏预览时可用于提示演讲人更详细的幻灯片内容细节
通过has_notes_slide来判断幻灯片是否有备注,通过以下代码可以获得幻灯片的备注信息
if slide.has_notes_slide:
text_frame = slide.notes_slide.notes_text_frame
print("备注文本:", text_frame.text)
若想修改备注信息,直接通过text指定即可
text_frame = slide.notes_slide.notes_text_frame
text_frame.text = "被修改的备注信息"
1.1.6 设置幻灯片标题
title_placeholder = slide.shapes.title
title_placeholder.text = 'Air-speed Velocity of Unladen Swallows'
几乎所有的幻灯片布局都有标题占位符,当布局被应用时,任何基于布局的幻灯片都会继承这个占位符。访问幻灯片标题是一种常见操作,它在形状树中有专门的属性:
1.2 一些ppt元素/组件
1.2.1 特殊符号
可以参考:MsoAutoShapeType
PENTAGON
Pentagon
PIE
Pie
PIE_WEDGE
Pie
PLAQUE
Plaque
PLAQUE_TABS
Plaque Tabs
1.2.2 placeholders
通过占位符可以访问PPTX 里面所有的元素,看
例子1(使用占位符):
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[8])
for shape in slide.placeholders:
print('%d - %s' % (shape.placeholder_format.idx, shape.name))
0 - Title 1
1 - Picture Placeholder 2
2 - Text Placeholder 3
通过遍历slide.placeholders
可以知道这个slide不同元素的内容,并且可以定位他,比如:
slide.placeholders[1]
<pptx.parts.slide.PicturePlaceholder object at 0x10d094590>
slide.placeholders[2].name # 该placeholders的名称
'Text Placeholder 3'
此时定位了之后,就可以直接进行一些操作,比如插入一张图片:
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[8])
placeholder = slide.placeholders[1] # idx key, not position
placeholder.name
'Picture Placeholder 2'
placeholder.placeholder_format.type # 该placeholder的格式是什么
PICTURE (18)
picture = placeholder.insert_picture('my-image.png')
例子2:
from pptx import Presentation
# 创建一个新的 Presentation 对象
prs = Presentation()
# 获取一个包含主标题和副标题的幻灯片版式
title_slide_layout = prs.slide_layouts[0]
# 将幻灯片加入到PPT中
slide = prs.slides.add_slide(title_slide_layout)
# 获取主标题
title = slide.placeholders[0]
# 获取副标题
subtitle = slide.placeholders[1]
title.text = "Hello, World!"
subtitle.text = "python-pptx create it"
# 保存创建的PPT文件
prs.save('G:/simple_ppt/test/test1.pptx')
通过placeholders定位到主标题与副标题,并进行文本替换
1.2.3 PPTX中的距离:Cm / Inches, Emu, Cm, Mm, Pt, and Px
在pptx中的距离有:Inches, Emu, Cm, Mm, Pt, and Px
其中,Cm代表厘米;Inches英尺(基本一个正方形slide,大概10英尺);Mm代表毫米;pt代表浮点长度;px代表像素点
from pptx.util import Cm
1.3 删除幻灯片
def delete_slide(prs, slide_index):
slides = list(prs.slides._sldIdLst)
prs.slides._sldIdLst.remove(slides[slide_index])
传入一个Presentation对象和指定第几张幻灯片,第一张索引从0开始
prs = Presentation('G:/simple_ppt/奖状模板.pptx')
delete_slide(prs, 0) # 删除第一张幻灯片
save_ppt = "G:/simple_ppt/test/blog_test_template.pptx"
prs.save(save_ppt)
2 pptx-python关联架构
2.1 生成文本框与段落 add_textbox
文本框的一些属性展示:
from pptx import Presentation
pptx_test = Presentation('aa.pptx' )
slide = pptx_test.slides[0]
# 一些类属性
pptx_test.slides[0].shape.has_text_frame # 判断该shape是否为文本框
pptx_test.slides[0].shape.name # 该shape的名称
pptx_test.slides[0].shape.text # 该shape文本框所有的文本
pptx_test.slides[0].shape.text_frame.text # 该shape文本框所有的文本,暂时不确定与上面一个的区别
# 看该shape下面所有文本片段
for paragraph in pptx_test.slides[0].shape.text_frame.paragraphs:
for run in paragraph.runs: # 逐行读入
print(run.text)
案例:
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE
from pptx.util import Inches,Pt
prs=Presentation()
# 设定slide的框架
blank_slide_layout=prs.slide_layouts[6]
# 新增一页slide
slide=prs.slides.add_slide(blank_slide_layout)
#设置要新建的文本框的位置
left = top = width = height = Inches(1)
#实例化一个文本框
txBox = slide.shapes.add_textbox(left, top, width, height)
#设置文件框的类型
tf=txBox.text_frame
#给定文本框里的文字
tf.text='This is text inside a textbox'
#添加段落,向下在添加段落文字
p=tf.add_paragraph()
#给新增加的段落添加文字
p.text="This is a second add_paragraph that's bold"
#给新添加的段落文字设置为粗体
p.font.bold=True
#再在这个文本框中新建一个段落
p=tf.add_paragraph()
#设置新段落的文字
p.text="This is a third paragraph that's big"
#设置新添加的段落文字的字号为40
p.font.size=Pt(40)
#保存新建的PPT。
prs.save(r'C:/Users/Administrator/Desktop/test.pptx')
生成的效果:
可以看到这里设定的文本框是需要额外定义的width, height
此时Inches
是其中一种衡量距离的单位
2.1.1 自动换行
文本框的属性:自动换行,输入的文本大于文本框的长度时
tf = tx_box.text_frame
tf.word_wrap = True
2.1.2 文本布局:居中对齐
文本框中的文本默认是上方对齐,可以使用tfvertical_anchor
来指定文本的布局方式
from pptx.enum.text import MSO_ANCHOR
tf = tx_box.text_frame
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
其他:
- TOP:将文本与文本框顶部对齐
- MIDDLE:垂直居中文本
- BOTTOM:将文本与文本框底部对齐
注意,这个只是指定了文本垂直方向上的移动,如想文本基于整个文本框居中需要指定段落的布局方式
设置文本段落布局可以通过设置p.alignment 的方式
from pptx.enum.text import MSO_ANCHOR, PP_ALIGN
tf = tx_box.text_frame
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
p0 = tf.paragraphs[0]
p0.text = '这是第一行段落'
p0.alignment = PP_ALIGN.CENTER
PP_ALIGN的参数有以下几个
- CENTER:居中对齐
- DISTRIBUTE:在一行中从左到右均匀分布
- JUSTIFY:每行都在页边空白处开始和结束,并调整单词之间的间距,使该行正好填满段落的宽度
- JUSTIFY_LOW:在单词之间使用少量空格进行对齐
- LEFT:默认的,左对齐
- RIGHT:右对齐
- THAI_DISTRIBUTE:泰语分散对齐,输入泰语时候指定
2.1.3 文本样式:字体、字号等
字体、字号、加粗、斜体、下划线、颜色、超链接等,这些样式通过font 来设置
from pptx import Presentation
from pptx.util import Cm, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import MSO_ANCHOR, PP_ALIGN
def test_blog_text_add():
prs = Presentation()
prs.slide_width = Cm(33.85)
prs.slide_height = Cm(19.02)
bullet_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(bullet_slide_layout)
# 添加文本框
tx_box = slide.shapes.add_textbox(left=Cm(2.58), top=Cm(1.16), width=Cm(28.47), height=Cm(5))
tf = tx_box.text_frame
tf.word_wrap = True # 自动换行
tf.vertical_anchor = MSO_ANCHOR.MIDDLE # 垂直居中
p0 = tf.paragraphs[0] # 第一行段落
p0.alignment = PP_ALIGN.CENTER # 设置段落文字居中
p0.line_spacing = 1.3 # 间距
p0.font.name = 'Arial Black' # 字体
p0.font.size = Pt(40) # 字号
p0.font.italic = True # 斜体
p0.font.bold = True # 粗体
p0.font.underline = True # 显示下划线
p0.font.color.rgb = RGBColor(255, 0, 0) # 设置红色
p0.text = 'Hello World!'
p1 = tf.add_paragraph() # 添加新段落
p1.text = '这是第二行段落'
run = p1.add_run()
run.text = "。第二行结尾直接添加文字"
run.hyperlink.address = 'https://www.baidu.com' # 添加超链接
prs.save("G:/simple_ppt/test/blog_test.pptx")
效果:
2.1.4 段落间距设置
可通过line_spacing指定
p0 = tf.paragraphs[0] # 第一行段落
p0.line_spacing = 1.3
2.1.5 文字大小自动改变
有时候我们要输入的文本太长,而文本框区域有限,此时可以指定文字的大小根据文本框的大小自动调整文字的大小
from pptx.enum.text import MSO_AUTO_SIZE
tf = tx_box.text_frame
tf.auto_size = MSO_AUTO_SIZE.TEXT_TO_FIT_SHAPE
MSO_AUTO_SIZE还有其它三个参数
- NONE:不进行任何自动调整,文字可以超出文本框的边界
- SHAPE_TO_FIT_TEXT:根据文字的内容自动调整文本框的宽度和高度,这样可以保持文字的大小不变
- TEXT_TO_FIT_SHAPE:根据文本框的大小自动调整文字的大小,这样可以让文字完全填充文本框
2.2 新增图片add_picture
图片相关属性:
from pptx import Presentation
pptx_test = Presentation('aa.pptx' )
slide = pptx_test.slides[0]
# 一些类属性
slide.shapes[6].image.content_type # 图片的格式
>>> 'image/png'
具体案例:
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE
from pptx.util import Inches,Pt
#要添加图片的路径
img_path=r'C:/Users/Administrator/Desktop/图片2.png'
#实例化一个PPT
prs=Presentation()
#设置要新建的PPT的样式
blank_slide_layout=prs.slide_layouts[6]
#根据设置的PPT布局样式新建一张空白的PPT
slide=prs.slides.add_slide(blank_slide_layout)
#设置图片的添加位置,以英寸为单位
left=top=Inches(1)
#在新建的PPT里添加指定的图片,到指定的位置
pic=slide.shapes.add_picture(img_path,left,top)
#重新调整图片距离左边的位置
left=Inches(5)
#设置图片的高度
height=Inches(5.5)
#将指定的图片再插入到新的位置,并设置图片的大小
pic=slide.shapes.add_picture(img_path,left,top,height=height)
#保存新建的PPT。
prs.save(r'C:/Users/Administrator/Desktop/test.pptx')
left和top表示图片左上角顶点分别距离幻灯片左边框和上边框的距离
2.3 特殊形状添加add_shape
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE
from pptx.util import Inches,Pt
#实例化一个PPT
prs=Presentation()
#设置新建PPT的布局样式:仅标题幻灯片版式
title_only_slide_layout=prs.slide_layouts[5]
#根据指定样式新建一张PPT,
slide=prs.slides.add_slide(title_only_slide_layout)
#把新建PPT中的所有形状对象shapes赋值给变量shapes
shapes=slide.shapes
#设置标题的文字
shapes.title.text='Adding an AutoShape'
#设置下面新建形状距所在页PPT左边的位置
left=Inches(0.93)
#设置下面新建形状距所在页PPT顶商的位置
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='Step 1'
#设置下面新建V形距左边的位置,0.4是V形的深度
left=left+width-Inches(0.4)
#设置新建V形的宽度
width=Inches(2.0)
#通过循环创建4个V形形状
for n in range(2,6):
#根据指定的位置、大小新建一个形状
shape=shapes.add_shape(MSO_SHAPE.CHEVRON,left,top,width,height)
#形状的文字
shape.text='Step %d'%n
#重新调整下一个形状距离左边的位置
left=left+width-Inches(0.4)
#保存新建的PPT。
prs.save(r'C:/Users/Administrator/Desktop/test.pptx')
其中:
MSO_SHAPE.PENTAGON
是特殊图形
形状图形的一些属性设置:
shape = slide.shapes.add_shape(MSO_SHAPE.STAR_5_POINT, left=Cm(28.83), top=Cm(6.87), width=Cm(3.7), height=Cm(3.7))
shape.rotation = 45 # 旋转图标45°
shape.shadow.inherit = True # 是否取消倒影显示
shape.fill.solid() # 设置这个后才能通过下面的fore_color来设置颜色
shape.fill.fore_color.rgb = RGBColor(255, 255, 0) # 修改填充颜色
shape.line.color.rgb = RGBColor(255, 0, 0) # 修改边框颜色
shape.line.width = Cm(0.1) # 修改边框宽度
还可以通过dash_style来指定边框的线条样式
from pptx.enum.dml import MSO_LINE
shape.line.dash_style = MSO_LINE.DASH # 设置边框为虚线
MSO_LINE其它参数:
- MSO_LINE.SOLID:实线
- MSO_LINE.DASH:短划线
- MSO_LINE.DASH_DOT:点划线
- MSO_LINE.DASH_DOT_DOT:双点划线
- MSO_LINE.LONG_DASH:长划线
- MSO_LINE.LONG_DASH_DOT:长点划线
- MSO_LINE.ROUND_DOT:圆点线
- MSO_LINE.SQUARE_DOT:方点线
五角星显示的效果
如果不想要图形的边框,可以使用以下方法将边框指定为透明
shape.line.fill.background()
2.4 新增表格add_table
官方:table
表格相关的属性:
from pptx import Presentation
pptx_test = Presentation('aa.pptx' )
slide = pptx_test.slides[0]
# 该table所有的cell都打印出来
for row in slide.shapes[2].table.rows:
for cell in row.cells:
print(cell.text)
具体案例:
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE
from pptx.util import Inches,Pt
#实例化一个PPT
prs=Presentation()
#设置将要新建的幻灯片版式
title_only_slide_layout=prs.slide_layouts[5]
#根据上面版式新建一张PPT
slide=prs.slides.add_slide(title_only_slide_layout)
#把新建PPT中所有的形状集合赋值给变量shapes
shapes=slide.shapes
#设置标题的文字
shapes.title.text='Adding a Table'
#设计将要新建的表格的行列数
rows=cols=2
#设置距离幻灯片左边及顶端的距离
left=top=Inches(2.0)
#设置表格的宽度
width=Inches(6.0)
#设置表格的高度
height=Inches(0.8)
#根据指定的行列数、位置、大小新建一个表格
table=shapes.add_table(rows,cols,left,top,width,height).table
#重新调整每列的宽度
table.columns[0].width=Inches(2.0)
table.columns[1].widht=Inches(4.0)
#设置表头的文字
table.cell(0,0).text='Foo'
table.cell(0,1).text='Bar'
#设置表体单元格里的文字
table.cell(1,0).text='Baz'
table.cell(1,1).text='Qux'
#保存新建的PPT。
prs.save(r'C:/Users/Administrator/Desktop/test.pptx')
table.cell
都是一个元素一个元素敲入
2.5 新增视频或音频 add_movie
video_path = 'G:/simple_ppt/res/movie.mp4'
slide.shapes.add_movie(video_path, Cm(11.66), Cm(6.22), Cm(8.11), Cm(5.07), mime_type='video/mp4')
视频显示的时候不会自动获取视频里的画面作为预览图,只会显示一个默认的喇叭图标,若想要根据视频的画面来生成预览图,可以借助OpenCV工具来获取视频帧存为图片,然后通过poster_frame_image参数来指定
import cv2
video_path = 'G:/simple_ppt/res/movie.mp4'
cap = cv2.VideoCapture(video_path)
cap.set(cv2.CAP_PROP_POS_FRAMES, 0) # 设置要获取的帧
ret, frame = cap.read()
cv2.imwrite(save_poster_temp, frame)
cap.release()
slide.shapes.add_movie(video_path, Cm(11.66), Cm(6.22), Cm(8.11), Cm(5.07), mime_type='video/mp4', poster_frame_image=save_poster_temp)
Python-pptx中并没有直接提供添加音频的方法,不过其实音频也可以通过add_movie来指定,只需要修改ime_type参数为audio/mp3
audio_path = 'G:/simple_ppt/res/audio.mp3'
slide.shapes.add_movie(audio_path, Cm(19.77), Cm(6.22), Cm(8.11), Cm(5.07), mime_type='audio/mp3')
效果如下
2.6 新增柱状图add_chart
来自:chart
from pptx import Presentation
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Inches
# create presentation with 1 slide ------
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[5])
# define chart data ---------------------
chart_data = CategoryChartData()
chart_data.categories = ['East', 'West', 'Midwest']
chart_data.add_series('Series 1', (19.2, 21.4, 16.7))
# add chart to slide --------------------
x, y, cx, cy = Inches(2), Inches(2), Inches(6), Inches(4.5)
slide.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED, x, y, cx, cy, chart_data
)
prs.save('chart-01.pptx')
图形输出为:
看一下第二个案例:
chart_data = ChartData()
chart_data.categories = ['East', 'West', 'Midwest']
chart_data.add_series('Q1 Sales', (19.2, 21.4, 16.7))
chart_data.add_series('Q2 Sales', (22.3, 28.6, 15.2))
chart_data.add_series('Q3 Sales', (20.4, 26.3, 14.2))
graphic_frame = slide.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED, x, y, cx, cy, chart_data
)
chart = graphic_frame.chart
带数据标签:
from pptx.dml.color import RGBColor
from pptx.enum.chart import XL_LABEL_POSITION
plot = chart.plots[0]
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
带题注Legend:
from pptx.enum.chart import XL_LEGEND_POSITION
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.RIGHT
chart.legend.include_in_layout = False
2.7 新增散点图XY_SCATTER
参考:https://daobook.github.io/python-pptx/user/charts.html
chart_data = XyChartData()
series_1 = chart_data.add_series('Model 1')
series_1.add_data_point(0.7, 2.7)
series_1.add_data_point(1.8, 3.2)
series_1.add_data_point(2.6, 0.8)
series_2 = chart_data.add_series('Model 2')
series_2.add_data_point(1.3, 3.7)
series_2.add_data_point(2.7, 2.3)
series_2.add_data_point(1.6, 1.8)
chart = slide.shapes.add_chart(
XL_CHART_TYPE.XY_SCATTER, x, y, cx, cy, chart_data
).chart
2.8 常见折线图 LINE
chart_data = ChartData()
chart_data.categories = ['Q1 Sales', 'Q2 Sales', 'Q3 Sales']
chart_data.add_series('West', (32.2, 28.4, 34.7))
chart_data.add_series('East', (24.3, 30.6, 20.2))
chart_data.add_series('Midwest', (20.4, 18.3, 26.2))
x, y, cx, cy = Inches(2), Inches(2), Inches(6), Inches(4.5)
chart = slide.shapes.add_chart(
XL_CHART_TYPE.LINE, x, y, cx, cy, chart_data
).chart
chart.has_legend = True
chart.legend.include_in_layout = False
chart.series[0].smooth = True
2.9 新增饼图PIE
chart_data = ChartData()
chart_data.categories = ['West', 'East', 'North', 'South', 'Other']
chart_data.add_series('Series 1', (0.135, 0.324, 0.180, 0.235, 0.126))
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
再来一个更好的案例(python pptx 表格 图表样式详解):
from pptx.chart.data import ChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_LABEL_POSITION
from pptx.util import Inches, Pt
from pptx import Presentation
from pptx.dml.color import RGBColor
prs = Presentation()
# 饼图
slide = prs.slides.add_slide(prs.slide_layouts[6])
chart_data = ChartData()
chart_data.categories = ['新闻', '论坛', '微博']
chart_data.add_series(name='负面数', values=[68, 25, 144])
left, top, width, height = Inches(9.5), Inches(2), Inches(15), Inches(15)
graphic_frame = slide.shapes.add_chart(chart_type=XL_CHART_TYPE.PIE, # 图表类型
x=left, y=top, # 图表区的位置
cx=width, cy=height, # 图表的宽和高
chart_data=chart_data)
chart = graphic_frame.chart
chart.chart_style = 10 # 图表样式 有1-48种 下方将列出这48种样式
plot = chart.plots[0]
# 设置数据标签
plot.has_data_labels = True # 显示数据标签
data_labels = plot.data_labels # 获取数据标签控制类
data_labels.show_category_name = True # 是否显示类别名称
data_labels.show_value = True # 是否显示值
data_labels.show_percentage = True # 是否显示百分比
data_labels.number_format = '0.0%' # 标签的数字格式
data_labels.position = XL_LABEL_POSITION.INSIDE_END # 标签位置
chart.font.name = '微软雅黑'
chart.font.size = Pt(10)
chart.font.bold = True
chart.font.color.rgb = RGBColor(255, 255, 255)
# 标题
chart.has_title = True
chart.chart_title.text_frame.clear()
new_title = chart.chart_title.text_frame.add_paragraph()
new_title.text = '各产业平台负面数量、占比'
new_title.font.size = Pt(18)
new_title.font.color.rgb = RGBColor(0, 0, 0)
prs.save('text.pptx')
结果:
其中,chart.chart_style 可以指定图表样式 ,有48种可能性:
chart.chart_style = 10
3 案例
3.1 遍历所有幻灯片文本 / 图片
from pptx import Presentation
prs = Presentation(path_to_presentation)
# text_runs will be populated with a list of strings,
# one for each text run in presentation
text_runs = []
for slide in prs.slides: # 遍历所有幻灯片
for shape in slide.shapes: # 遍历该幻灯片所有的元素
if not shape.has_text_frame: # 如果没有文本,则跳过
continue
for paragraph in shape.text_frame.paragraphs: # 指定这个模块当中的文本段落
for run in paragraph.runs: # 逐行读入
text_runs.append(run.text)
下面是遍历图片(https://blog.csdn.net/zhuwentao2150/article/details/134447696):
from pptx.enum.shapes import MSO_SHAPE_TYPE
prs = Presentation('G:/simple_ppt/test/blog_test_template.pptx')
save_dir = 'G:/simple_ppt/test/images'
for slide_no, slide in enumerate(prs.slides):
for shape_no, shape in enumerate(slide.shapes):
if shape.shape_type == MSO_SHAPE_TYPE.PICTURE: # 查找图片类型
image = shape.image
image_bytes = image.blob
image_filename = f"{save_dir}/slide_{slide_no}_image_{shape_no}.png"
with open(image_filename, "wb") as img_file:
img_file.write(image_bytes)
3.2 批量新增表格内容
案例来自 【python-pptx学习总结】:
from pptx import Presentation
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Inches
import pandas as pd
import numpy as np
from pptx.enum.text import PP_ALIGN
from pptx.enum.text import PP_PARAGRAPH_ALIGNMENT
from pptx.enum.text import MSO_ANCHOR
#shape.paragraphs[0].alignment = PP_ALIGN.CENTER
df = pd.read_csv("./bct_evaluation.csv",header=None)
ppt = Presentation()
slide=ppt.slides.add_slide(ppt.slide_layouts[6])# 空白幻灯片
rows,cols = df.shape
left = Cm(1)
top =Cm(5)
width = Cm(22)
height = Cm(3)
table = slide.shapes.add_table(rows,cols,left,top,width,height).table
table.columns[0].width = Cm(3)
table.rows[0].height =Cm(2)
data=df.values.tolist()
for row in range(rows):
for col in range(cols):
t=table.cell(row,col)
t.vertical_anchor = MSO_ANCHOR.MIDDLE # 垂直居中
t.text =str(data[row][col])
if(t.text[0].isdigit()):
#t.text=t.text[:5]# 0.xxx
t.text=str(np.round(float(t.text),3))
###### set font ######
for paragraph in t.text_frame.paragraphs:
#paragraph.alignment = PP_ALIGN.CENTER
paragraph.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER # 水平居中
for run in paragraph.runs:
run.font.size = Pt(8) # 设置字体
ppt.save("测试表格字符溢出.pptx")
#vertical_anchor = MSO_ANCHOR.MIDDLE
输出:
3.3 已有PPT模版进行替换
替换姓名 + 名称
3.3.1 不带格式替换
prs = Presentation('G:/simple_ppt/奖状模板.pptx')
slide_index = 0
slide = prs.slides[slide_index]
for shape in slide.shapes:
print("shape=", shape.name)
if shape.name == 'student_name':
shape.text = '孙悟空'
if shape.name == 'student_school':
shape.text = '花果山水帘洞'
if shape.name == 'cert_date':
current_date = datetime.now()
date_string = current_date.strftime("%Y年%m月%d日")
shape.text = date_string
save_ppt = "G:/simple_ppt/test/blog_test_template.pptx"
prs.save(save_ppt)
结果:
这里面有个问题就是shape.name
如何找到,就需要【选择窗格】
以WPS为例,打开选择窗格的方式:点击开始 -> 选择 -> 选择窗格,如下所示
此时就会在右侧栏目中出现选择窗格,显示当前幻灯片中所有对象元素的ID,点击对应对象ID即可进行修改
3.3.2 带格式替换
上面例子中是通过shape.text的方式来修改文本的,但这种方法有一个弊端,就是PPT中原有的文本框格式被擦除,所以这里推荐使用run文本段的方式修改文本
def replace_text(shape, content):
if not shape.has_text_frame: # 判断是否有文本框
return
tf = shape.text_frame
for paragraph in tf.paragraphs:
is_first_run = True
for run in paragraph.runs:
if is_first_run:
run.text = content
is_first_run = False
else:
run.text = ''
prs = Presentation('G:/simple_ppt/奖状模板.pptx')
slide_index = 0
slide = prs.slides[slide_index]
for shape in slide.shapes:
print("shape=", shape.name)
if shape.name == 'student_name':
replace_text(shape, '孙悟空')
if shape.name == 'student_school':
replace_text(shape, '花果山水帘洞')
if shape.name == 'cert_date':
current_date = datetime.now()
date_string = current_date.strftime("%Y年%m月%d日")
replace_text(shape, date_string)
save_ppt = "G:/simple_ppt/test/blog_test_template.pptx"
prs.save(save_ppt)
这个方法传入一个shape和文本内容,再通过has_text_frame判断shape中是否存在文本框,存在则进行更改文本操作,同时规避了有的文本框中存在多个词组run的问题,一个文本框中若存在多个词组,只需修改第一个词组即可,后续词组置空
3.3.3 修改幻灯片的图片
代码中通过删除原有shape中的图片,然后添加一个和原有shape大小位置一样的shape来指定图片,最后通过insert将新图片的shape元素插入到老图片shape的元素中,这样做是为了防止新添加的图片破坏层级关系,导致新添加的图片覆盖掉幻灯片中原来的元素
def replace_picture(shape, slide, slide_index, img_path):
sp_tree = slide.shapes._spTree
sp_tree.remove(shape._element)
new_shape = slide.shapes.add_picture(img_path, shape.left, shape.top, shape.width, shape.height)
sp_tree.insert(slide_index, new_shape._element)
if shape.name == 'slide_bg':
img_path = 'G:/simple_ppt/res/picture_bg.png'
replace_picture(shape, slide, slide_index, img_path)
4 参考文献:
https://www.dszhp.com/python-pptx.html
https://blog.csdn.net/zhuwentao2150/article/details/134015468