总篇136篇 2022年第11篇
前言
PPT已经是生活和工作中不可或缺的重要工具,尤其在汇报工作,产品介绍,提案申请等方面,能够帮助用户更加清晰的表达主题。文章重点讲解通过结合PPT模板和大数据分析结果,实现自动化生成PPT文件的过程,极大程度降低人工处理的复杂度,节约成本,提高时效性。
01
AutoPPT简介
汽车之家作为汽车行业垂直媒体领域的龙头老大,有众多厂商入驻,之家大数据在各方面的优秀表现,可以帮助厂商选择更好的产品和规划,因此,AutoPPT应运而生。大数据产品是本系统的硬实力,不仅提供计算后的需求数据和分类汇总,更能够提供支撑解决方案的逻辑分析。PPT模板是本系统的软实力,不仅与数据结合自动生成多方位数据模型,更是提供了一套完整的后续解决方案支撑体系。本系统生产的PPT,不单单是数字的堆积,更是具有自己清晰明确的观点和主张,从数据表现 -> 问题诊断 -> 解决方案 -> 产品展示,一条龙服务,帮助用户解决实实在在的问题 。使用AutoPPT系统,减少大量人工操作,省时省力,效率高;更重要的是,我们的产品,不仅有让用户舒服的视觉设计,还有一整套核心的内容设计 ,文以载道,软硬结合,是一套完整的PPT自动生成系统。
02
AutoPPT刷新数据系统架构
定时任务查询到新的PPT任务,将用户选择的所有PPT页组装成一个PPT模板文件
将PPT模板文件中的每一页组装DSS查询条件,向DSS系统请求查询数据
DSS查询数据结束,按照协定格式返回给PPT系统带有数据的Excel地址
定时任务检查到PPT模板文件的所有DSS数据均已返回,开始按照每页的Excel刷新PPT模板数据,刷新完成,用户需要的PPT就产生了
PPT页合并组装成一个PPT模板和将PPT模板数据刷新功能,在windows虚拟机中,Jar包注册成的Windows Service服务调用Python脚本完成。
03
AutoPPT刷新PPT模板数据功能
2)DSS返回的数据存放在Excel中,脚本使用win32.client打开PPT和Excel,主要原因是PPT图表中的内嵌Excel数据,需要从DSS返回的数据整体替换,win32在这方面的操作比较成熟。
04
AutoPPT脚本刷新PPT数据流程图
05
刷新前模板数据前提
合并成PPT整个模板
DSS数据完成
调用python脚本传参格式
pramMap = {
'pptUrl': 'D:\\pyProject\\PPT\\模板.pptx',
'pptExportUrl': 'D:\\pyProject\\PPT\\模板结果.pptx',
'templateParamMap': {
'1': {'titleInfo': {'文本框1': {'type': 2, 'value': '车系X'}}},
'9': {'excelUrl': 'D:\\pyProject\\PPT\\9.xlsx'
, 'chartInfo': {
'图表1': {'dataGetRule': 'A2:G10', 'dataGetWay':2,'sheetName':'Sheet3'}}
, 'tableInfo': {
'表格1': {'dataGetRule': '', 'dataGetWay': 1, 'sheetName': 'Sheet1'}}
, 'titleInfo': {'文本框1': {'type': 1, 'value': 'A1'}}}
}
示例参数为PPT第1和第9页的参数
06
脚本刷新PPT数据核心过程
import win32com.client as w3c
win32com.client as w3c:win32com 模块取名如此,是因为这个它在Linux系统里面不能用,对office的操作依赖于windows;使用别名是为了解决打开Excel应用报错(Dispatch('Excel.Application') ),通常情况不需要使用别名,如果有出现打开Office报错,可以参考使用别名。
#打开ppt应用 全局可使用
ppt = w3c.DispatchEx('PowerPoint.Application')
#打开Excel应用 全局可使用
excel = w3c.DispatchEx('Excel.Application')
PPT应用和Excel应用打开,不论打开的代码写在外面还是定义的方法里面,其他地方都可以使用这个变量,并且关闭Office应用,在脚本并发的情况下,会出现正在操作的Office文件失败,因为Offce应用已经被另一个进程关闭。
# 方式一
prs = ppt.Presentations.Open(pptUrl)
# 方式二
prs = w3c.DispatchEx('PowerPoint.Application').Presentations.Open(
pptUrl, WithWindow=False, ReadOnly=False)
正常情况下,使用PPT应用打开PPT文件可以使用方式一,但是由于AutoPPT系统以任务形式并发执行,存在并发多个Java服务调用python脚本执行操作PPT和EXCEL的情况,从而正在运行中的脚本操作PPT文件的时候,可能PPT应用已经被另一个脚本退出了,上面已经提到,打开的PPT应用是全局变量,执行关闭操作 ppt.Quit()
的时候,会关闭已经打开的所有PPT文件。改为文中的打开方式,且参数使用 WithWindow=False, ReadOnly=False,可支持并发操作。但是这种PPT打开方式,在office2013版本中,对PPT页的copy和paste方法不生效,因此合并PPT页面的脚本不能使用此方式打开,直接使用常用方法打开即可。
wb = excel.Workbooks.Open(wb_path)
打开EXCEL文件使用通用方式打开,对excel的内容使用到了区域数据复制功能,win32com包支持对某一区域或整个sheet页数据的拷贝。
shape_type = currentShape.Type
# 图表Chart
if shape_type == 3:
refreshChart(wb, chartInfo)
# 表格Table
elif shape_type == 19:
refreshTableNew(wb, tableInfo)
# 文本框Text
elif shape_type == 17:
refreshText(wb, titleInfo)
循环刷新每一页PPT数据,包括PPT的图表,表格,文本三种类型。每页刷新的方式是遍历每一页PPT的所有形状 prs.Slides.Shapes,判断形状的类型,判断形状的名称是否存在与脚本参数中,如果存在,表示这个形状的数据需要刷新。
这里使用循环每页PPT中所有的形状,来找到需要刷新的形状,而不是循环脚本参数中的形状名称,根据prs.Slides.Shapes(‘文本框5’) 这种方式来获取需要刷新的形状,是因为PPT中存在shape_type = 6 这种组合类型,因为不知道需要刷新的PPT形状是否在组合形状里,所以必须循环PPT的所有形状来确定需要刷新的形状。
# 激活PPT图表对象的Workbook工作簿
chart.ChartData.Activate()
# 更新PPT图表数据为excel中的有效数据
chart.ChartData.Workbook.Worksheets(1).UsedRange.Value = ws.UsedRange.Value
chart.ChartData.Workbook.Close()
通常的图表数据刷新,上面的方法即可以实现,但如果出现excel中的待刷新数据范围小于PPT模板中的示例数据范围,那么图表的展示会出现空的系列和空的图例,如右图所示。为了解决这种情况,有两种实现方法可供参考。
方法一:
上面的方法使用了删除无数据的系列和图例,实现了图表按照正常样式展示,但是这种方法不能实现excel表中的待刷新数据范围>PPT中图表的示例数据范围,也就是PPT中最多只能展示模板中示例数据那么多的数。而且在获取seriesCollection时,循环判断系列的值是否为空,需要sleep操作,理由于打开PPT应用一致,这里有获取不到系列值的情况存在,暂停一下,变量的值就获取到了。另外,由于每个图表图形数据范围不一致的时候,需要停留一段时间,如果这种图表较多,则有可能出现调脚本超时问题。
方法二:设置图表系列数据源和系列XValue ,自适应查询结果数据
# 设置图表系列数据源和系列XValue ,自适应查询结果数据
seriesSourceDataAddress = "B1:G10"
xValuesAddress = "A1:A10"
chart.SetSourceData("=" + pptSheetName + "!" + seriesSourceDataAddress)
chart.SeriesCollection(1).XValues = "=" + pptSheetName + "!" + xValuesAddress
以上方法因为重新设置了图表数据的数据范围,所以可以自适应图表系列和图例数据的减少或增加,适应性更强。这种方式适合于规规矩矩的行数据和列数据都是X轴或Y轴,不可用于,系列数据是xls中不连续的行或列的情况。
# 更新xls中数据到ppt表格中
celldata = content[row][col]
table.Cell(row, col).Shape.TextFrame.TextRange.Text = celldata
表格刷新的逻辑是将PPT表格中的示例数据清除,然后循环再将表格填满,整个过程安装字符串格式复制过来,PPT表格中展示的数据就是Excel数据中的样子,表格最多能够刷新的范围不超过模板示例中的表格范围。若有超出的数据需要展示,支持复制本页PPT的方式展示剩余数据。
# 用xls中数据替换
if type == 1:
shapeitem.TextFrame.TextRange.Text = worksheet.Range("A1").Value
# 用配置里的值替换
elif type == 2:
shapeitem.TextFrame.TextRange.Text = "替换文本"
# 文本添加超链接
elif type == 3:
shapeitem.TextFrame.TextRange.ActionSettings(1).Action
shapeitem.TextFrame.TextRange.ActionSettings(1).Hyperlink.Address = url
文本的数据刷新,支持三种方式,从Excel某个单元格中获取文本值,参数直接传递文本值,还可以设置超链接。设置超链接的时候,徐要先激活图形的Action设置。
pagerows = 10 # 每页更新10行数据
rowsCount = ws.UsedRange.Rows.Count
pagenum = math.ceil(rowsCount / pagerows) # 页数相除,向上取整
for index in range(pagenum - 1, -1, -1): # 倒序操作,刷新此页表格数据
# update the table data
if index > 0:
prs.Slides(slide).Duplicate() # 从第2页开始复制ppt页
复制PPT页需要注意的是必须倒序循环PPT页,每一页的复制也是倒序,这样才不会影响到参数指定页面序号的作用。用Duplicate方法直接复制到当前PPT的下方一页。如果用 copy,paste 由于Office版本的原因,可能出现复制不成功,复制到新页面的PPT,只有示例数据,无刚刚填充到PPT里的数据,包括服务器上OFFICE版本也不支持。
(1)文中属性和方法以大写字母开头
python语法结构有的版本比较严格,有的版本区分属性和方法是否大小写,通常情况大写字母开头比较稳妥,如果出现报错:不识别小写字母的方法或属性,尝试将属性和方法改为大写字母开头。
(2)使用Copy方法复制一页PPT到另外一个PPT时,2013版本Office的打开方式,需要使用常规打开方式不带参数Presentations.Open(ppt_path)
(3)如果出现获取到PPT页中某些信息为空,但实际数据并不为空,可用sleep()解决。
07
展望未来
AutoPPT的能力会逐步开放给公司内部其他部门或业务线使用,在技术层面,系统也会不断提升接入的便捷性、多样性,扩展对PPT其他图形的数据刷新操作,如图片,视频,3D模型等,更好更灵活的适用更多业务场景。未来可期,敬请期待!
作者简介
汽车之家
王建梅
主机厂事业部
2015年加入汽车之家,现任职于主机厂事业部技术团队,负责汽车之家电商业务系统、数科业务系统、AutoPPT自动生成工具等研发工作。