2023年11月26日发(作者:)

Python⾃动化之操作PPT--更新模板数据,减少重复操作

使⽤Python操作PPTX之保留原PPT模板只更改数据

Python⾃动化之操作PPT

⽇常⼯作中会遇见很多重复性的操作,利⽤Python可以让我们从繁忙的⼯作中解脱出来。本次要分析的就是运⽤Python操作PPT以实现⾃

动化⽣产PPT⽂件。

需求分析

⼯作中⼀同事需要结合Excel数据来制作PPT报告,以便甲⽅更好的看到商品部分指标的变化趋势。⽬前同事已经做好了⼀个模板⽂件,需

要完成将它运⽤到其他数据上。

PPT样式如下:

问题分析以及思路分享

原需求是想运⽤Python来⽣成PPT⽂件,于是需要了解到Python操作PPT的库,根据这个库来⽣成想要的PPT⽂件。

第⼀次尝试

由于第⼀次接触到Python操作PPT,在⽹上得知,Python操作PPT的库为python-pptx。于是安装python-pptx.

pip install python-pptx

安装完之后就可以对pptx进⾏操作了。

由于第⼀次使⽤有些操作不是很熟,阅读了⽹上的⼀些案例,结合 便开始⼀顿操作了。

可当正要操作是便发现,⽹上的⼤多数教程都是如何创建⼀页简单的PPT,讲到了Presentation,占位符等对象,可如上图所⽰,我操作的

是⽣成⼀个图表,还有⼀个表格,当PPT播放时,折线图还有⼀个动态的过程。于是我陷⼊了沉思,这个轮⼦我可造不了,对于python-

pptx我还不是很了解,这可不能快速的完成⾃动化的任务。

第⼆次尝试

虽然我不能创建PPT,但是⽬前已经有⼀个做好的模板PPT,借助于前段时间做过的⽣成报告证书的经历,报告证书是其中⼤多数数据不变,

变化商品名称和⽇期然后输出pdf⽂件,在模板⽂件中运⽤占位符就可以解决。于是顺着这个思路,我能否通过读取PPT模板,修改其中的

部分数据,⽽不改变结构,那么问题也就解决了。

于是运⽤python-pptx读取pptx⽂件,获取该对象,对该对象进⾏操作。

此时不得不打开官⽅⽂档了解其属性⽅法,⼀遍对其更好的操作。

慢,这样⼀来不⼜是进⼊了造轮⼦的阶段吗,我并不需要对pptx库进⾏全⾯的了解,核⼼是对数据进⾏替换。于是我只需要知道原PPT中⼀

个数据对应的属性⽅法是什么就可以了(有点像爬⾍),通过值找到对应的标签。下⾯正式开始。

读取pptx⽂件,读取⼀些基本知道该对象的属性⽅法

from pptx import Presentation

prs = Presentation("")

slides = prs.slides

number_pages = len(slides)

page = slides[0]

print(dir(page.shapes))

有上⾯输出可以得到 每个PPT页⾯的对象都为⼀个slider,每页中出现的内容都在中。

可以发现有如下属性:

‘adjustments’, ‘auto_shape_type’, ‘click_action’, ‘element’, ‘fill’, ‘get_or_add_ln’, ‘’,

has_chart

’, ‘has_text_frame’, ‘height’, ‘is_placeholder’, ‘left’, ‘line’, ‘ln’, ‘name’, ‘part’,

has_table

‘placeholder_format’, ‘rotation’, ‘shadow’, ‘shape_id’, ‘shape_type’, ‘text’, ‘text_frame’, ‘top’,

‘width’。

结合对pptx的初步了解,

text是和⽂字相关的,table是和表格相关的,chart是和图表相关的,其他的有⼀些边框⼤⼩,填充字体等属性。于是接着尝试

for shape in page.shapes:

# print(dir(shape))

if shape.has_chart:

print("ok")

if shape.has_tacle:

print("ok")

果然,返回的结果都是ok,也就是刚好和原来PPT中的折线图以及表格相对应。(感觉发现了新世纪的⼤门)

接着就是分别对chart和table进⾏操作了。(由于⾛了很多坑这⾥的顺序和实际完成的顺序不太⼀样)

table进⾏操作

table做为⼀个表格对象,从原图就可以看出,table有如下⼏种属性:变宽间距,字体颜⾊,字体形式,字体⼤⼩,对齐⽅式。刚好这⾥在

table对象都有了很好的体现。⽽我要做的就是如何修改这些达到要求。这其中对于字体颜⾊,有些原pptx的颜⾊在python-pptx中并读不

出来,这⾥的⼩技巧就是通过取⾊器获取原ppt⽂件中字体的RGB颜⾊,然后⽤python创建这样的⼀个颜⾊对象,来填充之前的属性。

for shape in page.shapes:

if shape.has_table:

table = shape.table

# tableopenpyxl

获取的⼀个格,类似

ii = 2

j = 1

cell = table.cell(ii, j + 1)

#

填充的数据

da = get_da(ci, j + 1)

pr = cell.text_frame.paragraphs[0].runs[0]

pr.text = da

#

字体⼤⼩

pr.font.size = Pt(11)

if da == "-" or da == "0%":

#

颜⾊

pr.font.color.rgb = RGBColor(0, 0, 0)

elif "-" in da:

pr.font.color.rgb = RGBColor(156, 0, 6)

else:

pr.font.color.rgb = RGBColor(84, 130, 53)

#

字体

pr.font.name = "Arial"

⼤功告成,table的给中属性和实际使⽤吻合很⾼。

chart进⾏操作

在对chart进⾏操作时,可以得到chart本⾝的属性。于是直接查看chart的属性和⽅法:

for shape in page.shapes:

if shape.has_chart:

chart = shape.chart

print(dir(chart))

chart_data = ChartData(chart)

cart = chart_data.categories

for s in cart:

print(s)

print(s.label)

for s in chart.series:

print(s.data_labels.show_value)

print(s.name)

可以找到chart有如下属性:

‘category_axis’, ‘chart_style’, ‘chart_title’, ‘chart_type’, ‘element’, ‘font’, ‘has_legend’, ‘has_title’,

‘legend’, ‘part’, ‘plots’, ‘replace_data’, ‘series’, ‘value_axis’

这些和Python中的图都很相似,于是我尝试获取到了图表中的值也惊奇的发现,视乎离成功更近⼀步了。下⼀步就是想如何改变这些值成

新的值了。于是我发现了replace_data⽅法,是否运⽤replace⽅法就可以完成操作了,于是我查找了相关replace的使⽤⽅式,通过不断

努⼒发现数据可以该但是并不是我想要的样⼦。没有了之前的动态显⽰过程,操作过程也⽐较复杂,当我在ppt编辑数据时,原数据居然没

有变化,我深知这事还没有结束。于是我去查找API发现其中这样⼀个描述

class ries

A data point series belonging to an area plot.

...

values

Read-only. A sequence containing the float values for this series, in the order they appear on the chart.

也就是说我获取到的图表区,部分参数是只读的,仔细⼀想图表是原数据的⼀种可视化表现,这⾥的chart对象只是图表的展⽰对象去,其

数据也相当于⼀个备份,改变chart属性时并没有实际改变源数据,所以只会在图形上⼀时的显⽰更改后的效果,不说这个过程有多复杂,

最终也不能实际完成⼯作。

于是我在这⾥卡住了。

最终的解决

由于上述问题⼀时卡住了我,我就先去忙其他的活了,可这终究是⼀到坎,我想着越过它。于是顺着上⾯的思路,加上实际的操作,每次⼈

⼯操作都是点击编辑数据之后,复制粘贴来完成。这样⼀想,python读了了ppt⽂件,将其转换为⼀个对象,表格,可以看得见的图标,都

可以在这个对象中找到,那编辑数据处的原数据应该也在原始的shape对象中。我得找到它。

我查看了chart_part属性,这让我眼前⼀亮[‘before_marshal’, ‘’, ‘’, ‘’, ‘content_type’,

blobchartchart_workbook

‘drop_rel’, ‘load’, ‘load_rel’, ‘new’, ‘package’, ‘part’, ‘part_related_by’, ‘partname’,

‘partname_template’, ‘relate_to’, ‘related_parts’, ‘rels’, ‘target_ref’]

这其中就有chart,我欣喜的是发现了***chart_workbook***,这让我想起了Excel,python中操作Excel的openpyxl中就有workbook。于

是我得好好的找找如何修改这个Excel⽂件的⽅法。

初步我发现了chart_workbook有如下属性和⽅法

class ChartWorkbook(builtins.object)

| ChartWorkbook(chartSpace, chart_part)

|

| Provides access to the external chart data in a linked or embedded Excel

| workbook.

|

| Methods defined here:

|

| __init__(self, chartSpace, chart_part)

| Initialize self. See help(type(self)) for accurate signature.

| # xlsxblobworkbook

使⽤⽂件的格式数据更新这个

| update_from_xlsx_blob(self, xlsx_blob)

| Replace the Excel spreadsheet in the related |EmbeddedXlsxPart| with

| the Excel binary in *xlsx_blob*, adding a new |EmbeddedXlsxPart| if

| there isn't one.

|

| ----------------------------------------------------------------------

| Data descriptors defined here:

|

| __dict__

| dictionary for instance variables (if defined)

|

| __weakref__

| list of weak references to the object (if defined)

|

| xlsx_part

| Return the related |EmbeddedXlsxPart| object having its rId at

| `c:chartSpace/c:externalData/@rId` or |None| if there is no

| `<c:externalData>` element.

发现chart_workbook中有⼀个blob⼆进制⽂件,这⾥经过不断尝试确定excel的内容就是以⼆进制存在blob中,如此凭着试⼀试的⼼态,

我以⼆进制形式读了⼀个xlsx⽂件,然后结合update_from_xlsx_blob⽅法,想着能不能更新数据。

wbda = open("","rb").read()

#

遍历每⼀个幻灯⽚的形状

for shape in pager.shapes:

# print(_chart)

if shape.has_chart:

# print(help(shape))

chart_part = shape.chart_part

chart_workbook = chart_part.chart_workbook

chart_workbook.update_from_xlsx_blob(wbda)

chart = shape.chart

#

是否能直接更新表格不需要⼈⼯处理,实际并不能

# chart.__init__(chartSpace=chart._chartSpace,chart_part=chart_part)

运⾏完成,打开新⽣产的⽂件,第⼀眼发现折线图并没有改变,觉得⾃⼰⼜失败了,可当我点击编辑数据后,折线图⽴刻发⽣了变化,播放

PPT原来的折线图的动态过程还在。总算是⼤功告成了,唯⼀美中不⾜的就是最后还需要⼿动点⼀下编辑数据。当然这个可以交个Python

去做,暂时想到的就是Python模拟⼈去点击,相关的知识下次再分享了。

⼩结

本次使⽤Python借助PPT模板⾃动⽣成同样样式的PPT。这其中⾛了很多弯路,让我学会了很多东西,强化了对⼀些知识的认识。

1:解决问题时要有不同的思路,⽬的是⽣成同样样式的PPT,那么可以尝试⾃⼰直接⽤Python⽣成,也可以直接对已经完成的模板进⾏修

改。亦或者是不直接操作使⽤python-pptx库,使⽤⾃动化控制软件去模拟⼈的操作⾏为,等等,只要最终问题得到了解决那就已经是⼀种

进步

2:⼀切皆对象,对象就有属性和⽅法,通过阅读API⽂档并结合实际操作可以快速的了解⼀个库。⽽实际对象转换时,⾁眼看的见的数据

或者图形都有可能转换成python中的对象,那么实际ppt所包含的字体,颜⾊,变宽,⼤⼩,图形,表格等都会在python转换的对象中存

在,结合实际问题,就可以合理运⽤属性和⽅法来快速掌握⼀个库的使⽤。完成任务。