该内容已被发布者删除 该内容被自由微信恢复
文章于 2017年4月2日 被检测为删除。
查看原文
被用户删除
其他

用 Python 制作 Powerpoint 演示文稿

2015-10-29 伯乐在线 Python开发者

(点击上方公号,可快速关注)


简介


不管你爱不爱,Powerpoint都被广泛应用于商务场合。文章不会争辩Powerpoint的优点,而是向你展示如何用Python使创建Powerpoint幻灯片自动化,以便去除掉在使用Powerpoint过程中一些单调乏味的工作。


幸运的是,有一个优秀的用于创建和更新PowerPoint文件的Python库:。该库的API非常详细,所以很容易使用。唯一棘手的部分是理解PowerPoint文档的结构,包括各种总体布局和元素。一旦你了解了基础知识,自动创建你自己的PowerPoint幻灯片会相对容易很多。本文将通过一个例子研究和分析一些pandas的Excel数据,创建一些可嵌入在PowerPoint文件里的图表。


PowerPoint文件的基础


Python-pptx可以创建空白PowerPoint文件,但大多数人会喜欢在一个根据自己的内容设定好的的模板上工作。Python-pptx的API支持这个预定义的过程并且非常简单,只要你知道关于你的模板的几件事就好了。


在深入一些代码示例之前,你需要了解两个关键部分:幻灯片布局和占位符。在下面的图片你可以看到两种不同的布局以及模板占位符的一个例子,你可以把内容填充在其中。


在下面的图片中,你可以看到,我们使用的是布局0,在幻灯片的第一页有一个占位符。


这幅图中,我们使用了外观完全不同的布局1。


为了让您更轻松地使用自己的模板,我创建了一个简单的独立脚本,这个脚本使用一个模板,并用各种元素来标记这个模板。

我不会一行一行地解释下面的代码,但是你可以自己在github上看,下面是完成主要工作的函数:


def analyze_ppt(input, output):

""" 读入文件并分析结构。

输出文件包含标记信息,使生成后面的PowerPoint模板更容易。

"""

prs = Presentation(input)

# 每个PowerPoint文件有多种布局

# 循环找出不同的元素位置

for index, _ in enumerate(prs.slide_layouts):

slide = prs.slides.add_slide(prs.slide_layouts[index])

# 不是每张幻灯片都有标题

try:

title = slide.shapes.title

title.text = 'Title for Layout {}'.format(index)

except AttributeError:

print("No Title for Layout {}".format(index))

# 遍历所有占位符,并通过索引和类型识别它们

for shape in slide.placeholders:

if shape.is_placeholder:

phf = shape.placeholder_format

# 不要覆写仅仅是一个特殊占位符的标题

try:

if 'Title' not in shape.text:

shape.text = 'Placeholder index:{} type:{}'.format(phf.idx, shape.name)

except AttributeError:

print("{} has no text attribute".format(phf.type))

print('{} {}'.format(phf.idx, shape.name))

prs.save(output)


这个函数的基本流程是通过循环并创建每一个包含在源PowerPoint文件中的布局实例。然后在每一页幻灯片上,将填充一个标题(如果有的话)。最后,它会遍历所有包含在模板中的占位符并显示占位符索引以及类型。


如果你想自己试试:


python analyze_ppt.py simple-template.ppt simple-template-markup.ppt


参考输入和输出文件,看看你得到什么。


创建你自己的幻灯片


对于数据收集和分析,我将从复制一些通用Excel报告的分析。这篇文章对Pandas数据操作解释得更加细致,所以这将使你在深入代码之前便对它非常了解,这对你肯定非常有用。


让我们从程序的输入和基本命令开始:


from __future__ import print_function

from pptx import Presentation

from pptx.util import Inches

import argparse

import pandas as pd

import numpy as np

from datetime import date

import matplotlib.pyplot as plt

import seaborn as sns

# 函数在这里运行

if __name__ == "__main__":

args = parse_args()

df = pd.read_excel(args.report.name)

report_data = create_pivot(df)

create_chart(df, "report-image.png")

create_ppt(args.infile.name, args.outfile.name, report_data, "report-image.png")


在我们创建命令行参数之后,我们将源Excel文件读入Pandas数据框架,然后,我们使用数据框架作为输入来创建Pivot_table总结:


def create_pivot(df, index_list=["Manager", "Rep", "Product"],

value_list=["Price", "Quantity"]):

"""

取一个数据框并创建一个pivot table,

将它作为数据框pivot table返回

"""

table = pd.pivot_table(df, index=index_list,

values=value_list,

aggfunc=[np.sum, np.mean], fill_value=0)

return table



如果这对你来说没有意义,请参考生成的通用Excel报告。


接下来的一个分析是建立一个简单的销售业绩表:


def create_chart(df, filename):

# 通过这个函数创建一个简单的柱状图保存在文件中给予数据框

df['total'] = df['Quantity'] * df['Price']

final_plot = df.groupby('Name')['total'].sum().order().plot(kind='barh')

fig = final_plot.get_figure()

# 和PowerPoint占位符相同的大小

fig.set_size_inches(6, 4.5)

fig.savefig(filename, bbox_inches='tight', dpi=600)


这里是一个缩小版的图片:


我们有一张表格以及一个完成了的透视表。现在我们将要把这些信息嵌入到一个基于给定模版的新建的PowerPoint文件中。


在我继续深入之前,有几件事需要我们注意。你需要知道你想要怎么样的布局,以及你想填充什么样的内容。在看analyze_ppt.py输出时我们知道,标题幻灯片是布局0,它拥有一个标题而且在占位符1处有一个副标题。


这是我们用来创建我们的输出Powerpoint文件的函数的开始部分:


def create_ppt(input, output, report_data, chart):

# 读取输入PowerPoint,并将它作为输出文件的模板。

prs = Presentation(input)

# 用analyze_ppt的输出来得到该用什么布局和占位符

# 首先创建一张幻灯片

title_slide_layout = prs.slide_layouts[0]

slide = prs.slides.add_slide(title_slide_layout)

title = slide.shapes.title

subtitle = slide.placeholders[1]

title.text = "Quarterly Report"

subtitle.text = "Generated on {:%m-%d-%Y}".format(date.today())


此代码创建了一个基于我们的输入文件的新的演示文稿,在幻灯片上添加了主标题和副标题,看起来就是这样的:



很酷吧?


下一步将我们的图片插入到幻灯片里去。


从我们前面的分析中我们知道,我们要用幻灯片布局的第8种,所以我们创建了一个新的幻灯片,添加了一个标题,然后在占位符1的位置上添加了一个图片、最后一步在占位符2处添加了副标题。


# 创建一个汇总表

graph_slide_layout = prs.slide_layouts[8]

slide = prs.slides.add_slide(graph_slide_layout)

title = slide.shapes.title

title.text = "Sales by account"

placeholder = slide.placeholders[1]

pic = placeholder.insert_picture(chart)

subtitle = slide.placeholders[2]

subtitle.text = "Results consistent with last quarter"


这就是我们的杰作:



在演示的最后部分,我们将根据他们的销售业绩为每一个管理者创建一个表格。


这就是我们将要实现的样子:



在PowerPoint中创建表格既有优点也有缺点。优点是,现在我们有API来创建一个表格了,缺点是你不能轻易地使用内置的API来将一个Pandas数据框架变成表格。然而,我们很幸运,有人已经为我们做了所有的工作并且实现。


这段出色的代码需要一个数据框,并将其转换为PowerPoint兼容表。我擅自截取了一部分在我的程序里。源代码有更多的功能,我没有使用,但是我建议你可以从仓库里check out一份,并用在你自己的代码中。


# 为每一个manager创建一张幻灯片

for manager in report_data.index.get_level_values(0).unique():

slide = prs.slides.add_slide(prs.slide_layouts[2])

title = slide.shapes.title

title.text = "Report for {}".format(manager)

top = Inches(1.5)

left = Inches(0.25)

width = Inches(9.25)

height = Inches(5.0)

# 重置索引将pivot table扁平化

# 在幻灯片上创建表格

df_to_table(slide, report_data.xs(manager, level=0).reset_index(),

left, top, width, height)

prs.save(output)


该代码将每一个“manager”从数据透视表中取出,并且构建了一个包含汇总数据的简单数据框。然后使用df_to_table将数据框转换为一个PowerPoint兼容表。


如果你想自己运行,完整的代码是这个样子:


python create_ppt.py simple-template.pptx sales-funnel.xlsx myreport.pptx


所有的相关文件都可以在 上找到。


结语


我真的很喜欢使用Python来解决现实业务问题的原因之一是,我常常惊喜于Python强大丰富的功能可以解决我的难题。在这种特定的情况下,使用PowerPoint不单单是一种享受,它在许多情景中还是必需品。

读完这篇文章后,你应该知道,下次你被要求创建一批PowerPoint报告就有希望了。请记住这篇文章,看看你是否能找到一种方法来自动完成单调乏味的工作!



Python开发者

微信号:PythonCoder

可能是东半球最好的 Python 微信号

--------------------------------------

投稿网址:top.jobbole.com

商务合作QQ:2302462408

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存