← 返回自动化办公目录
← 返回学习笔记首页
专题: Python 自动化办公系统学习
关键词: Python, 自动化办公, python-pptx, PPT图表, 动画, 母版定制, XML操作, 媒体嵌入, Python
一、图表深度定制
python-pptx 在基础图表创建之上提供了极为丰富的图表定制能力,支持多达 27 种图表类型,涵盖柱状图、折线图、饼图、散点图、面积图、雷达图、气泡图等几乎所有 Office 图表种类。真正的进阶用法不在于创建简单图表,而在于对图表各个构成元素进行精细化控制,包括坐标轴范围与刻度、网格线样式、数据标签格式、误差线、趋势线、系列颜色与填充等。
多系列组合图是最常见的业务需求之一,例如在一张图表中同时展示"销售额"柱状图和"增长率"折线图。python-pptx 通过在同一个 Chart 对象中添加多个系列,并为每个系列独立设置图表类型来实现组合效果。核心在于使用 `add_series()` 方法添加系列后,通过 `plot` 对象的 `chart_type` 属性分别控制每个系列的渲染方式。
图表元素的精细化控制是区分基础与进阶的关键。坐标轴方面,可以设置最小值、最大值、主要刻度单位、对数刻度、标签角度、数字格式等。网格线可以控制主要网格线和次要网格线的颜色、线型、透明度。数据标签可以显示值、百分比、系列名称、类别名称,并能自定义标签位置(居中、靠上、靠左等)和字体格式。误差线支持固定值、百分比、标准偏差和自定义值四种类型。这些控制全部通过 python-pptx 的 API 实现,无需手动操作 PowerPoint。
# 示例1:创建多系列组合图(柱状图+折线图)
from pptx import Presentation
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_LABEL_POSITION
from pptx.dml.color import RGBColor
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6]) # 空白版式
# 创建图表数据
chart_data = CategoryChartData()
chart_data.categories = ['Q1' , 'Q2' , 'Q3' , 'Q4' ]
chart_data.add_series('销售额(万)' , (120 , 180 , 150 , 210 ))
chart_data.add_series('增长率(%)' , (15 , 25 , 12 , 30 ))
# 将图表添加到幻灯片
chart_frame = slide.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED, # 先创建柱状图
100 , 100 , 800 , 450 , chart_data
).chart
# 将第二个系列改为折线图
plot = chart_frame.plots[0 >
plot.chart_type = XL_CHART_TYPE.COLUMN_CLUSTERED # 整体类型
series_growth = plot.series[1 ]
series_growth.chart_type = XL_CHART_TYPE.LINE_MARKERS # 单独设为折线
# 设置数据标签
data_labels = series_growth.data_labels
data_labels.show_value = True
data_labels.label_position = XL_LABEL_POSITION.ABOVE
prs.save('combo_chart.pptx' )
# 示例2:误差线与坐标轴精细化控制
from pptx import Presentation
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE, XL_ERR_BAR_TYPE, XL_TICK_MARK
from pptx.oxml.ns import qn
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
chart_data = CategoryChartData()
chart_data.categories = ['A' , 'B' , 'C' , 'D' ]
chart_data.add_series('测量值' , (23.5 , 28.1 , 25.7 , 30.2 ))
chart_frame = slide.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED,
50 , 80 , 850 , 480 , chart_data
)
chart = chart_frame.chart
plot = chart.plots[0 ]
series = plot.series[0 ]
# 添加误差线(标准偏差类型)
error_bar = series.error_bar
error_bar.type = XL_ERR_BAR_TYPE.STD_DEV
error_bar.amount = 1.5
# 坐标轴精细控制
value_axis = chart.value_axis
value_axis.minimum_scale = 0
value_axis.maximum_scale = 40
value_axis.major_unit = 5
value_axis.has_major_gridlines = True
value_axis.major_tick_mark = XL_TICK_MARK.CROSS
category_axis = chart.category_axis
category_axis.tick_labels.font.size = 140000 # 单位EMU,约14pt
category_axis.tick_labels.font.bold = True
prs.save('advanced_chart.pptx' )
# 示例3:气泡图与雷达图
from pptx import Presentation
from pptx.chart.data import BubbleChartData, RadarChartData
from pptx.enum.chart import XL_CHART_TYPE
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 气泡图需要X值、Y值和气泡大小
bubble_data = BubbleChartData()
bubble_data.add_series('产品组合' , (
(10 , 20 , 15 ), # (x, y, size)
(25 , 35 , 30 ),
(40 , 15 , 22 ),
(60 , 45 , 28 ),
))
chart_frame = slide.shapes.add_chart(
XL_CHART_TYPE.BUBBLE, 50 , 50 , 500 , 380 , bubble_data
)
# 在同一页添加雷达图
radar_data = RadarChartData()
radar_data.categories = ['速度' , '力量' , '技巧' , '耐力' , '敏捷' ]
radar_data.add_series('选手A' , (85 , 70 , 95 , 60 , 80 ))
radar_data.add_series('选手B' , (75 , 90 , 65 , 85 , 70 ))
chart_frame2 = slide.shapes.add_chart(
XL_CHART_TYPE.RADAR, 600 , 50 , 500 , 380 , radar_data
)
prs.save('bubble_radar.pptx' )
图表类型对照表
图表大类 枚举值 说明
柱状图 COLUMN_CLUSTERED / COLUMN_STACKED 簇状/堆积柱状图
条形图 BAR_CLUSTERED / BAR_STACKED 簇状/堆积条形图
折线图 LINE / LINE_MARKERS 折线/带标记折线
饼图 PIE / DOUGHNUT 饼图/圆环图
面积图 AREA / AREA_STACKED 面积/堆积面积
散点图 XY_SCATTER / XY_SCATTER_SMOOTH 散点/平滑散点
气泡图 BUBBLE / BUBBLE_THREE_EFFECT 气泡/三维气泡
雷达图 RADAR / RADAR_FILLED 雷达/填充雷达
股票图 STOCK_HIGH_LOW_CLOSE 高低收盘
曲面图 SURFACE / SURFACE_WIREFRAME 曲面/线框曲面
二、高级表格技术
python-pptx 的表格功能远不止基本的行列创建。在实际业务场景中,经常需要设计复杂的表格布局,包括合并单元格、拆分单元格(在PPT中合并后不可拆分,需要在逻辑层预先规划)、单元格级别的样式控制(填充色、渐变、边框宽度与颜色、文字方向与对齐)、以及对表格数据进行批量样式应用。表格是最直观的数据呈现方式,在管理报告、项目计划、对比分析等场景中频繁使用。
单元格样式控制是高级表格的核心。每个 Cell 对象都提供了丰富的样式属性:fill 控制背景填充(支持纯色、渐变、图片纹理);margin 控制单元格内边距;vertical_anchor 控制垂直对齐方式(顶部、居中、底部);font 控制字体样式。边框控制较为特殊,需要通过 XML 操作每个边框线(左、右、上、下、内斜线)的样式。python-pptx 提供了 TableCell 的 `border` 属性,可以精确设置每条边框的宽度、颜色和线型。
在实际报表生成中,表格数据绑定是一个重要概念。通过从 Excel 或数据库读取数据,自动填充到 PPT 表格中,并根据数据特征(如正数/负数、完成率等)自动应用不同的条件格式。例如,当某单元格数值超过阈值时自动标记为红色背景,当数据为负数时使用绿色字体,这种条件格式化极大地提升了报表的可读性。
# 示例1:创建复杂表格并设置单元格样式
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 创建6行4列表格
rows, cols = 6 , 4
left, top, width, height = Inches(0.5 ), Inches(0.5 ), Inches(9 ), Inches(4 )
table_shape = slide.shapes.add_table(rows, cols, left, top, width, height)
table = table_shape.table
# 设置列宽
col_widths = [Inches(2.5 ), Inches(2.5 ), Inches(2 ), Inches(2 )]
for i, w in enumerate(col_widths):
table.columns[i].width = w
# 头行样式
headers = ['产品名称' , '销售额' , '完成率' , '状态' ]
for i, h in enumerate(headers):
cell = table.cell(0 , i)
cell.text = h
cell.fill.solid()
cell.fill.fore_color.rgb = RGBColor(0x2E , 0x7D , 0x32 )
cell.vertical_anchor = MSO_ANCHOR.MIDDLE
for paragraph in cell.text_frame.paragraphs:
paragraph.alignment = PP_ALIGN.CENTER
for run in paragraph.runs:
run.font.color.rgb = RGBColor(0xFF , 0xFF , 0xFF )
run.font.size = Pt(14 )
run.font.bold = True
# 数据行
data = [
['产品A' , '¥128,000' , '92%' , '达标' ],
['产品B' , '¥95,000' , '68%' , '警告' ],
['产品C' , '¥210,000' , '115%' , '超额' ],
['产品D' , '¥72,000' , '51%' , '未达标' ],
['合计' , '¥505,000' , '82%' , '-' ],
]
for r, row_data in enumerate(data, start=1 ):
for c, val in enumerate(row_data):
cell = table.cell(r, c)
cell.text = val
cell.vertical_anchor = MSO_ANCHOR.MIDDLE
for paragraph in cell.text_frame.paragraphs:
paragraph.alignment = PP_ALIGN.CENTER
for run in paragraph.runs:
run.font.size = Pt(12 )
# 条件格式化
if c == 2 : # 完成率列
val_num = float(val.strip('%' ))
cell.fill.solid()
if val_num >= 100 :
cell.fill.fore_color.rgb = RGBColor(0xC8 , 0xE6 , 0xC9 ) # 绿色
elif val_num >= 70 :
cell.fill.fore_color.rgb = RGBColor(0xFF , 0xF3 , 0xCD ) # 黄色
else :
cell.fill.fore_color.rgb = RGBColor(0xFF , 0xCD , 0xD2 ) # 红色
prs.save('advanced_table.pptx' )
# 示例2:合并单元格与边框控制
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.oxml.ns import qn
from lxml import etree
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
table_shape = slide.shapes.add_table(5 , 4 , Inches(1 ), Inches(1 ), Inches(8 ), Inches(3.5 ))
table = table_shape.table
# 合并单元格:将第0行第0-3列合并为标题行
table.cell(0 , 0 ).merge(table.cell(0 , 3 ))
table.cell(0 , 0 ).text = '2025年度销售业绩概览'
table.cell(0 , 0 ).fill.solid()
table.cell(0 , 0 ).fill.fore_color.rgb = RGBColor(0x1B , 0x5E , 0x20 )
for p in table.cell(0 , 0 ).text_frame.paragraphs:
p.alignment = PP_ALIGN.CENTER
for r in p.runs:
r.font.size = Pt(16 )
r.font.color.rgb = RGBColor(0xFF , 0xFF , 0xFF )
r.font.bold = True
# 表头行再合并两列
table.cell(1 , 0 ).merge(table.cell(1 , 1 ))
table.cell(1 , 2 ).merge(table.cell(1 , 3 ))
# 设置边框样式(通过XML操作)
tbl = table._tbl
tblPr = tbl.find(qn('a:tblPr' ))
if tblPr is None :
tblPr = etree.SubElement(tbl, qn('a:tblPr' ))
# 为所有单元格设置边框
for cell in table._tbl.iter(qn('a:tc' )):
tcPr = cell.find(qn('a:tcPr' ))
if tcPr is None :
tcPr = etree.SubElement(cell, qn('a:tcPr' ))
# 添加细边框
ln_l = etree.SubElement(tcPr, qn('a:lnL' ))
ln_l.set('w' , '6350' ) # 0.5pt
ln_r = etree.SubElement(tcPr, qn('a:lnR' ))
ln_r.set('w' , '6350' )
ln_t = etree.SubElement(tcPr, qn('a:lnT' ))
ln_t.set('w' , '6350' )
ln_b = etree.SubElement(tcPr, qn('a:lnB' ))
ln_b.set('w' , '6350' )
prs.save('merged_table.pptx' )
表格设计的最佳实践包括:避免过多的单元格合并(PPT中合并后不易拆分)、合理设置行高列宽、使用交替行背景色提高可读性、对关键数据使用条件格式突出显示。在生成数百页的报表时,建议先创建表格样式函数,对整表进行统一样式应用,再对特定单元格做个别调整,这样可以大幅提高代码效率和一致性。
三、母版与布局深度定制
母版(Slide Master)和版式(Slide Layout)是 PowerPoint 中最强大的设计基础设施。python-pptx 允许程序化地访问和修改母版中的占位符布局、主题颜色方案、背景样式、字体方案等。理解母版体系是制作企业级统一风格演示文稿的前提。一个标准的母版包含多个版式(如标题版式、内容版式、空白版式等),每个版式定义了该类型页面的占位符位置、大小和默认样式。
占位符(Placeholder)布局规则是母版定制的核心。在 python-pptx 中,通过 `slide_layout.placeholders` 可以访问版式上预定义的占位符。在添加幻灯片时,可以使用 `slide_layout.placeholders[idx].insert_text()` 方法直接填充占位符内容。更高级的用法是使用 `placeholder_format` 属性判断占位符类型(标题、正文、图片、图表等),然后针对不同类型的占位符执行不同的填充逻辑。
主题色(Theme Color)控制演示文稿的整体色彩体系。python-pptx 通过 XML 操作可以修改母版的 `theme` 元素中的颜色方案,包括背景色、文字色、强调色、超链接色等。修改主题色后,所有基于该母版的幻灯片都会自动应用新配色。背景样式的控制同样通过 XML 层级实现,可以设置纯色背景、渐变背景、图片/纹理填充等。对于大型企业模板库,多重母版管理是常见需求,一个演示文稿可以包含多个母版,每个母版对应不同的章节风格(如封面章节使用深色母版、正文章节使用浅色母版)。
# 示例1:访问和修改版式占位符
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
prs = Presentation()
# 查看所有版式及其占位符
for idx, layout in enumerate(prs.slide_layouts):
print(f'版式 {idx}: {layout.name}' )
for ph in layout.placeholders:
print(f' 占位符 idx={ph.placeholder_format.idx}, '
f'类型={ph.placeholder_format.type}, '
f'名称={ph.name}' )
# 使用版式添加幻灯片并填充占位符
slide_layout = prs.slide_layouts[1 ] # 标题和内容版式
slide = prs.slides.add_slide(slide_layout)
# 通过占位符索引填充内容
title = slide.shapes.title
title.text = '2025年度市场分析报告'
title.text_frame.paragraphs[0 ].alignment = PP_ALIGN.LEFT
# 填充正文占位符(通常idx=1是正文区)
content = slide.placeholders[1 ]
content.text = '本报告基于全年市场数据进行分析...\n包含4个核心板块:\n1. 市场概况\n2. 竞争分析\n3. 趋势预测\n4. 战略建议'
prs.save('layout_placeholders.pptx' )
# 示例2:通过XML修改主题色和背景
from pptx import Presentation
from pptx.oxml.ns import qn
from lxml import etree
prs = Presentation('template.pptx' ) # 基于模板
# 修改主题色方案——将强调色改为品牌蓝色
master = prs.slide_masters[0 ]
theme = master.slide_master_element.find(qn('p:clrMap' ))
# 通过theme element找到颜色方案
theme_elem = master.element.find(qn('p:clrMap' ))
if theme_elem is None :
theme_elem = etree.SubElement(master.element, qn('p:clrMap' ))
# 修改幻灯片背景(第一张幻灯片设置渐变背景)
slide = prs.slides[0 ]
bg = slide.background
bg.fill.solid()
bg.fill.fore_color.rgb = RGBColor(0xF0 , 0xF8 , 0xFF )
# 更复杂的操作:创建自定义背景XML
bg_elem = slide.background._element
bg_pr = bg_elem.find(qn('p:bgPr' ))
if bg_pr is None :
bg_pr = etree.SubElement(bg_elem, qn('p:bgPr' ))
# 添加纯色填充
solidFill = etree.SubElement(bg_pr, qn('a:solidFill' ))
srgbClr = etree.SubElement(solidFill, qn('a:srgbClr' ))
srgbClr.set('val' , 'F0F8FF' )
prs.save('theme_customized.pptx' )
# 示例3:多重母版管理——不同章节使用不同母版
from pptx import Presentation
prs = Presentation()
# 方法:将不同风格的内容放在不同版式下实现视觉差异
# 不同版式可以模拟不同"章节风格"
# 封面:使用版式0(标题版式)
cover_layout = prs.slide_layouts[0 ]
cover_slide = prs.slides.add_slide(cover_layout)
cover_slide.shapes.title.text = '季度财报分析'
# 目录页:使用版式1(标题+内容版式)但隐藏内容区
toc_layout = prs.slide_layouts[1 ]
toc_slide = prs.slides.add_slide(toc_layout)
toc_slide.shapes.title.text = '目录'
# 内容页:自定义版式使用
content_layout = prs.slide_layouts[1 ]
content_slide = prs.slides.add_slide(content_layout)
# 纯内容页(无标题区):使用空白版式自行添加
blank_layout = prs.slide_layouts[6 ]
blank_slide = prs.slides.add_slide(blank_layout)
txBox = blank_slide.shapes.add_textbox(Inches(0.5 ), Inches(0.5 ), Inches(9 ), Inches(3 ))
txBox.text = '全幅内容区域,无占位符干扰'
prs.save('multi_master.pptx' )
四、动画控制
python-pptx 的动画控制是相对进阶且文档较少的领域,但它的确提供了对 PowerPoint 动画的基本读写支持。动画控制的核心在于操作形状(Shape)的 `animation_settings` 属性,以及对 XML 层级的动画元素(`p:anim`、`p:animEffect`、`p:set` 等)进行直接操作。动画类型分为四大类:进入动画(Entrance)、强调动画(Emphasis)、退出动画(Exit)和动作路径动画(Motion Paths)。
动画的触发方式控制动画何时开始执行。python-pptx 支持三种触发方式:点击时(ON_CLICK)、与上一动画同时(WITH_PREVIOUS)、上一动画之后(AFTER_PREVIOUS)。在自动化生成演示文稿时,合理使用"与上一动画同时"和"之后"可以创建出流畅的自动播放效果,无需人工点击。动画参数的精细化控制包括动画速度(Duration,以秒为单位)、延迟时间(Delay,动画开始前的等待时间)、方向(Direction,如"自左侧"进入等)、力度(如弹跳效果的弹跳次数)等。
多动画序列是复杂演示的关键。在一张幻灯片上,可以为多个形状设置不同的动画,并按特定顺序排列。例如:先飞入标题(自左侧,0.5秒),然后淡入图表(0.8秒延迟),最后逐条显示要点列表(逐条弹跳进入)。这种多层次的动画序列可以引导观众的注意力,增强演示的叙事效果。需要注意的是,python-pptx 对动画的高级参数(如缓动函数 easing、触发动画的触发器 trigger)需要通过直接操作 XML 来实现,因为高层 API 尚未完全封装这些功能。
# 示例1:基本动画设置
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
from pptx.oxml.ns import qn
from lxml import etree
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 添加标题
title_box = slide.shapes.add_textbox(Inches(1 ), Inches(0.5 ), Inches(8 ), Inches(1 ))
tf = title_box.text_frame
tf.text = '2025年度业绩报告'
tf.paragraphs[0 ].font.size = Pt(36 )
# 添加副标题
sub_box = slide.shapes.add_textbox(Inches(1 ), Inches(1.6 ), Inches(8 ), Inches(0.8 ))
sub_box.text = '亮点回顾与未来展望'
# 为标题添加进入动画(飞入)
slide._element.append(
etree.fromstring(
'<p:timing xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">'
'<p:tnLst>'
'<p:par>'
'<p:cTn id="1" dur="500" fill="hold">'
'<p:stCondLst>'
'<p:condEvt delay="0"/>'
'</p:stCondLst>'
'<p:childTnLst>'
'<p:par>'
'<p:cTn id="2" dur="500" fill="hold">'
'<p:stCondLst>'
'<p:condEvt delay="0"/>'
'</p:stCondLst>'
'<p:childTnLst>'
'<p:par>'
'<p:cTn id="3" dur="2000">'
'<p:stCondLst>'
'<p:condEvt delay="0"/>'
'</p:stCondLst>'
'<p:childTnLst>'
'<p:set>'
'<p:cBhvr>'
'<p:cTn id="4" dur="500"/>'
'<p:tgtEl>'
'<p:spTgt spid="%s"/>'
'</p:tgtEl>'
'<p:attrNameLst>'
'<p:attrName>ppt_x</p:attrName>'
'</p:attrNameLst>'
'</p:cBhvr>'
'</p:set>'
'</p:childTnLst>'
'</p:cTn>'
'</p:par>'
'</p:childTnLst>'
'</p:cTn>'
'</p:par>'
'</p:tnLst>'
'</p:timing>' % title_box.shape_id
)
)
prs.save('animation_basic.pptx' )
# 示例2:使用 python-pptx 内置动画设置(简化方式)
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import MSO_ANIMATION_TRIGGER
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 创建多个形状用于动画测试
shapes_data = [
('标题区域' , Inches(1 ), Inches(0.5 ), Inches(8 ), Inches(0.8 )),
('主要内容要点一:市场增长25%' , Inches(1 ), Inches(2 ), Inches(8 ), Inches(0.5 )),
('主要内容要点二:新产品线扩展' , Inches(1 ), Inches(2.8 ), Inches(8 ), Inches(0.5 )),
('主要内容要点三:海外市场突破' , Inches(1 ), Inches(3.6 ), Inches(8 ), Inches(0.5 )),
]
boxes = []
for text, left, top, width, height in shapes_data:
box = slide.shapes.add_textbox(left, top, width, height)
box.text = text
boxes.append(box)
# 每个形状的 animation_settings 允许设置触发方式
# 注意:python-pptx 的 animation_settings 功能有限,
# 复杂动画参数需要通过 XML 操作实现
for i, box in enumerate(boxes):
settings = box.animation_settings
if i == 0 :
settings.animate = 'after_prev' # 上一动画之后自动播放
else :
settings.animate = 'on_click' # 点击触发
prs.save('animation_trigger.pptx' )
# 示例3:动画序列控制(通过 XML 直接操作)
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.oxml.ns import qn
from lxml import etree
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 创建3个形状,每个要应用不同的动画序列
box1 = slide.shapes.add_textbox(Inches(1 ), Inches(1 ), Inches(3 ), Inches(1 ))
box1.text = '框1:首先显示'
box2 = slide.shapes.add_textbox(Inches(5 ), Inches(1 ), Inches(3 ), Inches(1 ))
box2.text = '框2:延迟显示'
box3 = slide.shapes.add_textbox(Inches(3 ), Inches(3.5 ), Inches(3 ), Inches(1 ))
box3.text = '框3:最后显示'
# 构建 timing XML(动画时间线)
# 使用 batchAdd 方式创建动画序列
sld_id = slide._element.get(qn('p:sldId' ) + '_attr' )
# 简单做法:通过元素树构建动画
timing_xml = '''<p:timing>
<p:tnLst>
<p:par>
<p:cTn id="1" dur="indefinite" restart="never">
<p:stCondLst>
<p:cond delay="indefinite"/>
</p:stCondLst>
<p:childTnLst>
<p:seq>
<p:cTn id="2" dur="indefinite" nextAc="seek">
<p:stCondLst>
<p:cond delay="0"/>
</p:stCondLst>
<p:childTnLst>
<p:par>
<p:cTn id="3" dur="2000" fill="hold">
<p:stCondLst>
<p:cond delay="500"/>
</p:stCondLst>
<p:childTnLst>
<p:set>
<p:cBhvr>
<p:cTn id="4" dur="1500"/>
<p:tgtEl>
<p:spTgt spid="''' + str(box1.shape_id) + '''"/>
</p:tgtEl>
<p:attrNameLst>
<p:attrName>style.visibility</p:attrName>
</p:attrNameLst>
</p:cBhvr>
</p:set>
</p:childTnLst>
</p:cTn>
</p:par>
</p:childTnLst>
</p:cTn>
</p:seq>
</p:childTnLst>
</p:cTn>
</p:par>
</p:tnLst>
</p:timing>'''
# 将 timing 元素添加到 slide 中可实现动画效果
# 注意:完整实现需要为每个形状重复上述 set 块
# 此处展示原理,实际生产代码建议使用封装库
print('动画序列已配置:框1(0.5s后) → 框2(1.5s延迟) → 框3(2.5s延迟)' )
prs.save('animation_sequence.pptx' )
五、XML底层操作
python-pptx 底层基于 Open XML 标准,所有 PowerPoint 文件实际上是一个 ZIP 包,内部包含一系列 XML 文件。理解 XML 架构是掌握 python-pptx 进阶能力的必由之路。每个 pptx 文件的核心 XML 包括:`ppt/presentation.xml`(演示文稿主结构)、`ppt/slides/slideN.xml`(每张幻灯片内容)、`ppt/slideMasters/slideMasterN.xml`(母版)、`ppt/theme/themeN.xml`(主题配色)、`ppt/charts/chartN.xml`(图表数据)等。
lxml 直接操作是突破 python-pptx 高层 API 限制的关键技术。python-pptx 内部使用 lxml 的 ElementTree 来管理 XML。通过访问形状的 `_element` 属性和 XML 命名空间工具 `pptx.oxml.ns.qn()`,可以直接对底层 XML 进行读写操作。这使我们能够实现高层 API 尚未支持的功能,如自定义数据标签格式、设置形状的三维效果、控制图表的系列间距、添加自定义 XML 属性等。
自定义 XML 元素的应用场景非常广泛。例如,在幻灯片中添加自定义数据属性用于后期处理、修改图表数据表的显示选项、设置 SmartArt 图形的高级参数、添加演示文稿的扩展属性(如版权信息、文档编号)等。通过 XML 操作,可以实现几乎任何 PowerPoint 本身支持的功能。熟练掌握 lxml 的 `find()`、`findall()`、`SubElement()`、`set()` 等方法,结合对 Open XML 规范的理解,可以解锁 python-pptx 的全部潜力。
# 示例1:探索 pptx 文件的 XML 结构
from pptx import Presentation
from pptx.oxml.ns import qn
from lxml import etree
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 添加一个形状
box = slide.shapes.add_textbox(100 , 100 , 500 , 200 )
box.text = 'XML 底层操作示例'
# 获取形状的原始 XML
element = box._element
xml_str = etree.tostring(element, pretty_print=True ).decode('utf-8' )
print('形状XML结构:' )
print(xml_str[:500 ])
# 遍历幻灯片所有元素的XML
for shape in slide.shapes:
print(f'形状: {shape.shape_type}, XML标签: {shape._element.tag}' )
# 检查是否存在扩展属性
extLst = shape._element.find(qn('p:extLst' ))
if extLst is None :
print(' 无扩展属性' )
# 查看 slide 的 XML 根元素
slide_xml = etree.tostring(slide._element, pretty_print=True ).decode('utf-8' )
print(f'\n幻灯片XML (前300字符):\n{slide_xml[:300]}' )
prs.save('xml_structure.pptx' )
# 示例2:通过 lxml 直接操作 XML 实现高级自定义
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.oxml.ns import qn
from lxml import etree
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 添加一个形状
box = slide.shapes.add_textbox(Inches(1 ), Inches(1 ), Inches(6 ), Inches(1.5 ))
box.text = '自定义XML属性演示'
# 直接操作底层 XML:修改形状属性
sp = box._element
spPr = sp.find(qn('p:spPr' ))
if spPr is None :
spPr = etree.SubElement(sp, qn('p:spPr' ))
# 添加自定义几何形状属性(圆角矩形)
prstGeom = spPr.find(qn('a:prstGeom' ))
if prstGeom is None :
prstGeom = etree.SubElement(spPr, qn('a:prstGeom' ))
prstGeom.set('prst' , 'roundRect' )
avLst = etree.SubElement(prstGeom, qn('a:avLst' ))
gd = etree.SubElement(avLst, qn('a:gd' ))
gd.set('name' , 'adj' )
gd.set('fmla' , 'val 5000' ) # 圆角半径
# 添加自定义扩展数据(在应用层使用)
extLst = etree.SubElement(sp, qn('p:extLst' ))
ext = etree.SubElement(extLst, qn('p:ext' ))
ext.set('uri' , '{D2B8EC00-9E62-4F6C-8C0B-123456789ABC}' )
# 在扩展中添加自定义 XML 数据
custom_data = etree.SubElement(ext, qn('p14:customData' ))
custom_data.set('xmlns:p14' , 'http://schemas.microsoft.com/office/powerpoint/2010/main' )
custom_data.set('id' , 'custom_shape_001' )
custom_data.set('created_by' , 'auto_script' )
print(f'自定义XML元素已添加, shape_id={box.shape_id}' )
prs.save('xml_custom.pptx' )
# 示例3:读取和修改 pptx 扩展属性
from pptx import Presentation
from pptx.oxml.ns import qn
from lxml import etree
import zipfile
import io
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
slide.shapes.title.text = 'XML属性测试'
# 保存到内存
buf = io.BytesIO()
prs.save(buf)
buf.seek(0 )
# 使用 zipfile 直接读取 pptx 内的 XML 文件
with zipfile.ZipFile(buf, 'r' ) as z:
# 列出所有 XML 文件
xml_files = [f for f in z.namelist() if f.endswith('.xml' )]
print('pptx 内部 XML 文件列表:' )
for f in xml_files[:10 ]:
print(f' {f}' )
# 读取演示文稿属性
with z.open('docProps/app.xml' ) as app_xml:
app_tree = etree.parse(app_xml)
ns = {'ap' : 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties' }
app_elem = app_tree.find('.//ap:Application' , ns)
print(f'应用程序: {app_elem.text if app_elem is not None else "N/A"}' )
# 创建新的演示文稿并添加文档属性
prs2 = Presentation()
core_props = prs2.core_properties
core_props.title = '自动化生成的PPT'
core_props.subject = 'python-pptx XML操作演示'
core_props.author = '自动脚本'
core_props.comments = '使用python-pptx和Open XML标准生成'
core_props.keywords = 'python, pptx, automation, xml'
print(f'文档属性已设置: {core_props.title}' )
prs2.save('xml_properties.pptx' )
六、媒体与嵌入
python-pptx 支持在演示文稿中嵌入多种媒体类型,包括视频(MP4、WMV、AVI等格式)、音频(MP3、WAV、MIDI等格式),以及超链接和动作按钮。媒体嵌入功能使得创建交互式、多媒体演示文稿成为可能。添加视频时,需要指定视频文件的路径,并通过 `MediaType` 枚举指定媒体类型。python-pptx 会自动将媒体文件打包到 pptx 文件中,确保迁移时不会丢失。
超链接是增强演示文稿交互性的重要手段。python-pptx 支持为任意形状(文本框、图片、形状等)添加超链接,可以链接到 URL、当前文档中的特定幻灯片、电子邮件地址或新文档。动作按钮(Action Button)是 PowerPoint 中的特殊形状,可以触发特定行为,如跳转到上一页、打开 URL、运行程序等。通过创建特定类型的形状并设置其动作设置,可以实现导航按钮的功能。
在实际应用中,媒体嵌入常用于产品演示、培训材料、数据报告等场景。例如,在季度财报 PPT 中嵌入 CEO 的视频致辞,或在产品发布 PPT 中添加演示视频。需要注意的是,嵌入的视频和音频文件会增加 pptx 文件的体积,建议控制媒体文件的大小(压缩视频、使用较低的比特率)。对于 Flash 和 ActiveX 控件,由于技术已逐步被淘汰,不推荐在新项目中使用。
# 示例1:嵌入视频和音频文件
from pptx import Presentation
from pptx.util import Inches, Emu
from pptx.enum.shapes import MSO_SHAPE
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 嵌入视频文件
video_path = 'demo_video.mp4'
try :
video_shape = slide.shapes.add_movie(
video_path,
Inches(1 ), Inches(0.5 ),
Inches(6 ), Inches(4 ),
poster_frame_image='poster.png' # 视频封面图
)
print(f'视频已嵌入, shape_id={video_shape.shape_id}' )
except FileNotFoundError:
print('视频文件不存在,跳过嵌入' )
# 嵌入音频文件
audio_path = 'background_music.mp3'
try :
audio_shape = slide.shapes.add_movie(
audio_path,
Inches(1 ), Inches(5 ),
Inches(0.5 ), Inches(0.5 ),
poster_frame_image=''
)
# 设置音频为自动播放
# 通过 XML 设置媒体播放选项
from pptx.oxml.ns import qn
from lxml import etree
media_elem = audio_shape._element.find(qn('p:vid' ))
if media_elem is None :
media_elem = audio_shape._element.find(qn('p:audio' ))
print(f'音频已嵌入, shape_id={audio_shape.shape_id}' )
except FileNotFoundError:
print('音频文件不存在,跳过嵌入' )
prs.save('media_embedded.pptx' )
# 示例2:添加超链接
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
# 添加文本框并设置超链接
left, top, width, height = Inches(2 ), Inches(2 ), Inches(6 ), Inches(1.5 )
txBox = slide.shapes.add_textbox(left, top, width, height)
tf = txBox.text_frame
# 添加超链接文字
p = tf.paragraphs[0 ]
p.alignment = PP_ALIGN.CENTER
run = p.add_run()
run.text = '点击访问官方网站'
run.font.size = Pt(18 )
run.font.color.rgb = RGBColor(0x00 , 0x56 , 0xB3 )
run.font.underline = True
# 设置超链接
run.hyperlink.address = 'https://www.example.com'
run.hyperlink.tooltip = '打开官方网站'
# 给形状添加超链接(点击整个形状区域触发)
txBox.click_action.hyperlink.address = 'https://www.example.com'
# 添加"内部跳转"超链接(跳转到演示文稿中的特定幻灯片)
slide2 = prs.slides.add_slide(prs.slide_layouts[6 ])
slide2.shapes.title.text = '目标幻灯片'
# 在第一张幻灯片添加跳转到第二张的链接
nav_box = slide.shapes.add_textbox(Inches(2 ), Inches(4 ), Inches(6 ), Inches(0.6 ))
nav_box.text = '跳转到下一页'
nav_box.click_action.hyperlink.slide = slide2 # 链接到特定幻灯片
prs.save('hyperlinks.pptx' )
七、数据驱动PPT
数据驱动 PPT 是 python-pptx 最强大的应用场景之一。其核心理念是从 Excel、CSV、数据库或 API 等数据源读取数据,自动化生成包含图表、表格和文本分析的演示文稿。这一能力对于需要定期生成报告的场景尤其有价值,如每周销售简报、月度财务报告、季度市场分析等。整套流程无需人工介入,即可从原始数据生成专业级别的 PPT 文件。
从 Excel 数据到 PPT 图表的完整管道包括三步:第一步使用 openpyxl 或 pandas 从 Excel 文件中提取数据并进行预处理(清洗、聚合、计算指标);第二步将处理后的数据填入 python-pptx 的 ChartData 对象;第三步创建图表并将其放置在幻灯片上,同时设置格式和样式。如果需要动态更新已有演示文稿中的图表,可以通过替换图表数据工作表(Excel Worksheet)的内容来实现,这种方式保留了已有的图表格式和动画设置。
批量生成幻灯片是数据驱动 PPT 的高级应用。基于模板幻灯片,通过循环遍历数据源中的每一行或每一组数据,自动复制模板并填充内容,可以在一分钟内生成数百张风格统一的幻灯片。常见应用包括:为每个销售代表生成个人业绩页、为每个产品线生成分析面板、为每个区域生成市场数据页。结合条件逻辑,还可以为不同数据状态应用不同的视觉样式(如未达标区域标红、超额完成区域标绿)。
# 示例1:从Excel读取数据生成PPT图表
from pptx import Presentation
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE
from pptx.util import Inches
import openpyxl
# 第一步:从 Excel 读取数据
wb = openpyxl.load_workbook('sales_data.xlsx' )
ws = wb.active
categories = []
series_data = []
for row in ws.iter_rows(min_row=2 , max_row=ws.max_row, values_only=True ):
categories.append(str(row[0 ]))
series_data.append(row[1 ])
print(f'从Excel读取了 {len(categories)} 条数据' )
# 第二步:填充到 ChartData
chart_data = CategoryChartData()
chart_data.categories = categories
chart_data.add_series('销售额' , series_data)
# 第三步:创建PPT并添加图表
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ])
chart_frame = slide.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED,
Inches(0.5 ), Inches(1 ),
Inches(9 ), Inches(5.5 ),
chart_data
)
# 添加标题
slide.shapes.title.text = '月度销售额分析(自动生成)'
prs.save('data_driven_chart.pptx' )
print('数据驱动PPT图表已生成' )
# 示例2:批量生成幻灯片(销售报告场景)
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
prs = Presentation()
# 销售数据(模拟从数据库/Excel读取)
sales_data = [
{'name' : '张三' , 'revenue' : 580000 , 'target' : 500000 , 'region' : '华东' },
{'name' : '李四' , 'revenue' : 420000 , 'target' : 500000 , 'region' : '华南' },
{'name' : '王五' , 'revenue' : 750000 , 'target' : 600000 , 'region' : '华北' },
{'name' : '赵六' , 'revenue' : 310000 , 'target' : 400000 , 'region' : '西部' },
]
# 批量生成幻灯片
for i, sales in enumerate(sales_data):
slide = prs.slides.add_slide(prs.slide_layouts[1 ]) # 使用标题+内容版式
# 填充标题
title = slide.shapes.title
title.text = f'{sales["name"]} - 销售业绩概览'
# 计算完成率
completion = (sales['revenue' ] / sales['target' ]) * 100
# 添加详细数据文本框
txBox = slide.shapes.add_textbox(
Inches(1 ), Inches(1.5 ),
Inches(8 ), Inches(3 )
)
tf = txBox.text_frame
tf.word_wrap = True
details = [
f'销售人员:{sales["name"]}' ,
f'所属区域:{sales["region"]}' ,
f'实际销售额:¥{sales["revenue"]:,}' ,
f'目标额:¥{sales["target"]:,}' ,
f'完成率:{completion:.1f}%' ,
f'状态:{"已达标" if completion >= 100 else "未达标"}' ,
]
for j, detail in enumerate(details):
if j == 0 :
p = tf.paragraphs[0 ]
else :
p = tf.add_paragraph()
p.text = detail
p.font.size = Pt(14 )
p.space_after = Pt(6 )
# 根据完成率设置不同的状态颜色
status_color = RGBColor(0x2E , 0x7D , 0x32 ) if completion >= 100 else RGBColor(0xE7 , 0x4C , 0x3C )
print(f'已生成第{i+1}张幻灯片: {sales["name"]}' )
prs.save('batch_sales_report.pptx' )
print(f'批量生成完成,共 {len(sales_data)} 张幻灯片' )
# 示例3:更新已有PPT中的图表数据
from pptx import Presentation
import openpyxl
from lxml import etree
import zipfile
import io
import shutil
import os
# 打开现有PPT
prs = Presentation('template_chart.pptx' )
# 遍历所有幻灯片中的所有形状,找到图表
chart_count = 0
for slide in prs.slides:
for shape in slide.shapes:
if shape.has_chart:
chart = shape.chart
chart_data = chart.chart_data
# 更新图表数据类别
chart_data.categories = ['一月' , '二月' , '三月' , '四月' ]
# 更新值
try :
series = chart_data.series[0 ]
new_values = (125 , 148 , 162 , 189 )
for i, val in enumerate(new_values):
try :
series.values[i] = val
except (IndexError, TypeError):
pass
chart_count += 1
except Exception as e:
print(f'更新图表失败: {e}' )
print(f'已更新 {chart_count} 个图表数据' )
prs.save('chart_data_updated.pptx' )
八、实战案例
实战案例是将上述所有技术融合应用的终极考验。本节展示三个典型的全流程自动化场景:季度财报PPT自动生成、市场调研报告自动化、以及数据大屏简报生成。每个案例都综合运用了图表深度定制、表格技术、母版布局、动画控制和数据驱动等多项技术,代表了 python-pptx 在企业级自动化中的最佳实践。
季度财报PPT自动生成是最常见的需求之一。完整流程包括:从财务系统导出数据(或读取Excel报表)、自动计算同比环比增长、创建多系列组合图展示收入构成、使用表格呈现各部门关键指标、应用条件格式化突出异常数据、生成封面和目录页、为每页添加规范的页脚信息。整个流程可以在 10 秒内完成原本需要 2-3 小时的手工制作工作。市场调研报告则更注重图表的多样性和数据的对比分析,需要大量使用雷达图、气泡图、堆积图等高级图表类型。
数据大屏简报是在单个页面内集中展示多个关键指标的高级应用。通过合理安排布局(如左上角放置趋势折线图、右上角放置饼图、中部放置核心指标卡片、底部放置数据表格),可以在单一幻灯片中呈现完整的业务概览。结合 python-pptx 的 XML 操作能力,还可以为不同指标卡片添加动画序列,在演示时按序展现,引导观众的注意力。这些实战案例展示 Python 自动化办公在处理复杂、重复性办公任务中的巨大价值。
# 案例1:季度财报PPT自动生成器
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_LEGEND_POSITION
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from datetime import datetime
def generate_quarterly_report(company_name, quarter, year, financial_data):
"""
自动生成季度财报PPT
Args:
company_name: 公司名称
quarter: 季度 (1-4)
year: 年份
financial_data: 财务数据字典
"""
prs = Presentation()
# ---- 第1页:封面 ----
slide_cover = prs.slides.add_slide(prs.slide_layouts[0 ])
slide_cover.shapes.title.text = f'{company_name}\n{year}年第{quarter}季度财报'
subtitle = slide_cover.placeholders[1 ]
subtitle.text = f'报告日期:{datetime.now().strftime("%Y年%m月%d日")}'
# ---- 第2页:财务概览 ----
slide_overview = prs.slides.add_slide(prs.slide_layouts[6 ])
txBox = slide_overview.shapes.add_textbox(
Inches(0.5 ), Inches(0.3 ), Inches(9 ), Inches(5.5 )
)
tf = txBox.text_frame
overview_text = [
'核心财务指标概览' ,
'' ,
f'营业收入:¥{financial_data["revenue"]:,.0f} (同比 {financial_data["revenue_growth"]:+.1f}%)' ,
f'营业成本:¥{financial_data["cost"]:,.0f} (同比 {financial_data["cost_growth"]:+.1f}%)' ,
f'净利润: ¥{financial_data["net_profit"]:,.0f} (同比 {financial_data["profit_growth"]:+.1f}%)' ,
f'毛利率: {financial_data["gross_margin"]:.1f}%' ,
f'净利率: {financial_data["net_margin"]:.1f}%' ,
f'每股收益:¥{financial_data["eps"]:.2f}' ,
]
for i, text in enumerate(overview_text):
if i == 0 :
p = tf.paragraphs[0 ]
p.font.size = Pt(28 )
p.font.bold = True
else :
p = tf.add_paragraph()
p.font.size = Pt(16 ) if i > 1 else Pt(8 )
p.space_after = Pt(4 )
p.text = text
# ---- 第3页:收入趋势图表 ----
slide_chart = prs.slides.add_slide(prs.slide_layouts[6 ])
chart_data = CategoryChartData()
chart_data.categories = ['Q1' , 'Q2' , 'Q3' , 'Q4' ]
chart_data.add_series(f'{year-1}' , financial_data['prev_year_revenue' ])
chart_data.add_series(f'{year}' , financial_data['curr_year_revenue' ])
chart_frame = slide_chart.shapes.add_chart(
XL_CHART_TYPE.COLUMN_CLUSTERED,
Inches(0.5 ), Inches(0.5 ), Inches(9 ), Inches(5.5 ),
chart_data
)
chart = chart_frame.chart
chart.has_legend = True
chart.legend.position = XL_LEGEND_POSITION.BOTTOM
chart.legend.include_in_layout = False
# 设置图表标题
chart.has_title = True
chart.chart_title.text_frame.paragraphs[0 ].text = '季度收入对比(万元)'
print(f'季度财报PPT生成完成:{company_name} {year}Q{quarter}' )
return prs
# 使用示例
financial_data = {
'revenue' : 12800000 , 'revenue_growth' : 15.3 ,
'cost' : 8500000 , 'cost_growth' : 8.7 ,
'net_profit' : 2800000 , 'profit_growth' : 22.5 ,
'gross_margin' : 33.6 , 'net_margin' : 21.9 ,
'eps' : 2.35 ,
'prev_year_revenue' : (2800 , 3100 , 2900 , 3500 ),
'curr_year_revenue' : (3200 , 3600 , 3400 , 4000 ),
}
# prs = generate_quarterly_report('示例科技', 4, 2025, financial_data)
# prs.save('quarterly_report.pptx')
print('财报自动生成函数已定义,传入财务数据即可调用' )
# 案例2:数据大屏简报生成
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.chart.data import CategoryChartData
from pptx.enum.chart import XL_CHART_TYPE
def create_dashboard(kpi_data):
"""
生成数据大屏简报幻灯片
Args:
kpi_data: 包含多个KPI指标的字典
"""
prs = Presentation()
slide = prs.slides.add_slide(prs.slide_layouts[6 ]) # 空白版式
# 背景色设置为深色
bg = slide.background
bg.fill.solid()
bg.fill.fore_color.rgb = RGBColor(0x1A , 0x1A , 0x2E )
# ---- 标题 ----
title_box = slide.shapes.add_textbox(Inches(0.5 ), Inches(0.2 ), Inches(9 ), Inches(0.6 ))
title_box.text = '经营数据大屏 · 实时监控'
for p in title_box.text_frame.paragraphs:
p.alignment = PP_ALIGN.CENTER
for r in p.runs:
r.font.size = Pt(28 )
r.font.color.rgb = RGBColor(0xFF , 0xFF , 0xFF )
r.font.bold = True
# ---- KPI 卡片(四角布局) ----
card_data = [
('总营收' , f'¥{kpi_data["total_revenue"]/10000:.1f}万' , f'+{kpi_data["revenue_growth"]:.1f}%' , Inches(0.3 ), Inches(1.0 )),
('活跃用户' , f'{kpi_data["active_users"]/10000:.1f}万' , f'+{kpi_data["user_growth"]:.1f}%' , Inches(6.5 ), Inches(1.0 )),
('订单量' , f'{kpi_data["orders"]:,}' , f'+{kpi_data["order_growth"]:.1f}%' , Inches(0.3 ), Inches(4.0 )),
('转化率' , f'{kpi_data["conversion"]:.1f}%' , f'{kpi_data["conversion_change"]:+.1f}pp' , Inches(6.5 ), Inches(4.0 )),
]
for title, value, change, left, top in card_data:
card = slide.shapes.add_shape(
1 , left, top, Inches(4.8 ), Inches(2.5 ) # MSO_AUTO_SHAPE.RECTANGLE
)
card.fill.solid()
card.fill.fore_color.rgb = RGBColor(0x25 , 0x2A , 0x4A )
card.line.fill.background()
# 卡片标题
tf = card.text_frame
tf.word_wrap = True
tf.paragraphs[0 ].alignment = PP_ALIGN.CENTER
for r in tf.paragraphs[0 ].runs:
r.font.size = Pt(14 )
r.font.color.rgb = RGBColor(0x8E , 0x9E , 0xBB )
# ---- 趋势图(中下方) ----
chart_data = CategoryChartData()
chart_data.categories = ['W1' , 'W2' , 'W3' , 'W4' ]
chart_data.add_series('营收趋势' , kpi_data['weekly_revenue' ])
chart_frame = slide.shapes.add_chart(
XL_CHART_TYPE.LINE_MARKERS,
Inches(0.3 ), Inches(6.8 ), Inches(9.4 ), Inches(2.5 ),
chart_data
)
print('数据大屏简报已生成' )
return prs
# 使用示例
kpi_data = {
'total_revenue' : 12850000 ,
'revenue_growth' : 15.3 ,
'active_users' : 85600 ,
'user_growth' : 8.7 ,
'orders' : 12350 ,
'order_growth' : 12.4 ,
'conversion' : 3.42 ,
'conversion_change' : 0.28 ,
'weekly_revenue' : (285 , 320 , 298 , 356 ),
}
# prs = create_dashboard(kpi_data)
# prs.save('dashboard.pptx')
print('数据大屏函数已定义,传入KPI数据即可调用生成' )
最佳实践总结: python-pptx 进阶应用的核心在于三点:一是理解 Open XML 架构,掌握通过 lxml 进行底层操作的能力;二是建立数据驱动的思维,将 PPT 生成视为数据到呈现的管道;三是模块化封装,将常用的图表样式、表格模板、布局逻辑封装成可复用的函数或类,减少重复代码。建议所有生产环境项目都建立模板库,包含企业标准的母版、配色方案和字体设置,通过程序化方式应用这些模板,确保输出的 PPT 保持统一的品牌风格。