python-pptx - Python 操作 PPT 幻灯片

文章目录


一、关于 python-pptx

python-pptx是一个用于创建、读取和更新PowerPoint(.pptx)文件的Python库。

一个典型的用途是从动态内容(如数据库查询、分析输出或JSON有效负载)生成PowerPoint演示文稿,可能是响应HTTP请求并下载生成的PPTX文件作为响应。

它可以在任何支持Python的平台上运行,包括macOS和Linux,并且不需要安装或许可PowerPoint应用程序。

它还可用于分析语料库中的PowerPoint文件,可能用于提取搜索索引文本和图像。

它也可以用来简单地自动化一两张幻灯片的制作,这将是乏味的,这就是这一切的开始。


设计哲学

python-pptx 旨在广泛支持PowerPoint格式(PPTX、PowerPoint 2007及更高版本),但其主要承诺是工业级,即适合在商业环境中使用。

保持这种稳健性需要高工程标准,包括全面的两级(e2e+单元)测试方案。

这一规程以开发工作/时间为代价,但我们认为可靠性是一项基本要求。


功能支持

python-pptx具有以下功能:

  • 往返任何Open XML演示文稿(.pptx文件),包括其所有元素
  • 添加幻灯片
  • 填充文本占位符,例如创建项目符号幻灯片
  • 将图像添加到任意位置和大小的幻灯片
  • 将文本框添加到幻灯片;操作文本字体大小和粗体
  • 将表格添加到幻灯片
  • 将自动形状(例如多边形、流程图形状等)添加到幻灯片
  • 添加和操作柱形图、条形图、折线图和饼图
  • 访问和更改核心文档属性,例如标题和主题
  • 还有许多其他人...

即使使用了所有python-pptx,PowerPoint文档格式也非常丰富,并且仍然存在python-pptx不支持的功能。


二、安装

python-pptx托管在PyPI上,因此使用pip安装很简单:

shell 复制代码
pip install python-pptx

python-pptx 依赖于lxml包和Pillow,现代版本的 Python图像库(PIL)。 图表功能取决于 XlsxWriter
pipeasy_install都会处理 满足您的这些依赖关系,但如果您使用setup.py 安装方法您需要自己安装依赖项。

目前python-pptx需要 Python 2.7或3.3或更高版本。

测试在Travis CI上针对2.7和3.8运行。


三、入门

一个快速入门的方法是尝试下面的一些示例,以了解如何使用python-pptx。

API 文档 可以帮助您与精细的细节 调用签名和行为。


1、你好世界!例子


python 复制代码
from pptx import Presentation

prs = Presentation()
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 = "Hello, World!"
subtitle.text = "python-pptx was here!"

prs.save('test.pptx')

2、Bullet 幻灯片示例


python 复制代码
from pptx import Presentation

prs = Presentation()
bullet_slide_layout = prs.slide_layouts[1]

slide = prs.slides.add_slide(bullet_slide_layout)
shapes = slide.shapes

title_shape = shapes.title
body_shape = shapes.placeholders[1]

title_shape.text = 'Adding a Bullet Slide'

tf = body_shape.text_frame
tf.text = 'Find the bullet slide layout'

p = tf.add_paragraph()
p.text = 'Use _TextFrame.text for first bullet'
p.level = 1

p = tf.add_paragraph()
p.text = 'Use _TextFrame.add_paragraph() for subsequent bullets'
p.level = 2

prs.save('test.pptx')

并非所有形状都可以包含文本,但那些总是至少有一个 段落,即使该段落为空并且在 形状。
_BaseShape.has_text_frame可用于确定形状是否 可以包含文本。(所有形状子类_BaseShape。)

_BaseShape.has_text_frameTrue_BaseShape.text_frame.paragraphs[0]返回第一段。

第一段的文本 可以使用text_frame.paragraphs[0].text

作为 一个快捷方式,可写属性_BaseShape.text_TextFrame.text用于完成相同的任务。

请注意 这最后两个调用删除了除第一个之外的所有形状段落 在设置它包含的文本之前。


3、add_textbox()示例


python 复制代码
from pptx import Presentation
from pptx.util import Inches, Pt

prs = Presentation()
blank_slide_layout = prs.slide_layouts[6]
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 paragraph that's bold"
p.font.bold = True

p = tf.add_paragraph()
p.text = "This is a third paragraph that's big"
p.font.size = Pt(40)

prs.save('test.pptx')

4、add_picture()示例


python 复制代码
from pptx import Presentation
from pptx.util import Inches

img_path = 'monty-truth.png'

prs = Presentation()
blank_slide_layout = prs.slide_layouts[6]
slide = prs.slides.add_slide(blank_slide_layout)

left = top = Inches(1)
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)

prs.save('test.pptx')

5、add_shape()示例


python 复制代码
from pptx import Presentation
from pptx.enum.shapes import MSO_SHAPE
from pptx.util import Inches

prs = Presentation()
title_only_slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(title_only_slide_layout)
shapes = slide.shapes

shapes.title.text = 'Adding an AutoShape'

left = Inches(0.93)  # 0.93" centers this overall set of shapes
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'

left = left + width - Inches(0.4)
width = Inches(2.0)  # chevrons need more width for visual balance

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)

prs.save('test.pptx')

表示每个可用自动形状的常量(如 MSO_SHAPEROUNDED_RECT、MSO_SHAPE. CHEVRON等)列在 自动形状类型页面。


6、add_table()示例


python 复制代码
from pptx import Presentation
from pptx.util import Inches

prs = Presentation()
title_only_slide_layout = prs.slide_layouts[5]
slide = prs.slides.add_slide(title_only_slide_layout)
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

# set column widths
table.columns[0].width = Inches(2.0)
table.columns[1].width = Inches(4.0)

# write column headings
table.cell(0, 0).text = 'Foo'
table.cell(0, 1).text = 'Bar'

# write body cells
table.cell(1, 0).text = 'Baz'
table.cell(1, 1).text = 'Qux'

prs.save('test.pptx')

7、从演示文稿中的幻灯片中提取所有文本

python 复制代码
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)

四、使用演示文稿

python-pptx允许您创建新的演示文稿以及对现有演示文稿进行更改。

实际上,它只允许您对现有演示文稿进行更改;只是如果你从一个没有任何幻灯片的演示文稿开始,起初感觉就像你在从头开始创建一个。

然而,演示文稿的外观很大程度上是由删除所有幻灯片时留下的部分决定的,特别是主题,幻灯片母版,以及源自母版的幻灯片布局。

让我们用例子一步一步地浏览它,从演示文稿可以做的两件事开始,打开它并保存它。


1、打开演示文稿

最简单的入门方法是在不指定要打开的文件的情况下打开一个新演示文稿:

python 复制代码
from pptx import Presentation

prs = Presentation()
prs.save('test.pptx')

这会从内置的默认模板创建一个新的演示文稿,并将其原封不动地保存到名为"test.pptx"的文件中。

需要注意的几件事:

  • 所谓的"默认模板"实际上只是一个没有任何幻灯片的幻灯片文件,与安装的python-pptx包一起存储。
    这与您从新安装的PowerPoint中创建新演示文稿的效果相同,这是一个基于"白色"模板的4x3长宽比演示文稿。
    嗯,除了它不包含任何幻灯片。
    默认情况下,PowerPoint总是在第一张幻灯片上添加空白。
  • 在保存之前,您不需要对其做任何操作。
    如果您想准确查看该模板包含的内容,只需查看它创建的"test.pptx"文件。
  • 我们称之为模板,但实际上它只是一个普通的PowerPoint文件,所有的幻灯片都被删除了。
    实际的PowerPoint模板文件(.pptx文件)有点不同。
    稍后可能会有更多信息,但您不需要它们来使用python-pptx。

2、真正打开演示文稿

好的,所以如果你想控制最终的演示文稿,或者如果你想改变现有的演示文稿,你需要用文件名打开一个:

python 复制代码
prs = Presentation('existing-prs-file.pptx')
prs.save('new-file-name.pptx')

注意事项:

  • 您可以通过这种方式打开任何PowerPoint 2007或更高版本的文件(PowerPoint 2003及更早版本中的. ppt文件不起作用)。
    虽然您可能还无法操作所有内容,但已经在其中的任何内容都可以加载和保存。
    功能集仍在构建中,因此您还不能添加或更改Notes Pages之类的内容,但如果演示文稿中有它们,python-pptx会很有礼貌地让它们单独存在,并且足够聪明地保存它们,而无需真正理解它们是什么。
  • 如果您使用相同的文件名打开和保存文件,python-pptx将乖乖地覆盖原始文件而不偷看。
    您需要确保这就是您的意图。

3、打开类似文件的演示文稿

python-pptx可以从所谓的类文件对象打开演示文稿。它也可以保存到类文件对象。

当您想通过网络连接或数据库获取源或目标演示文稿并且不想(或不允许)与文件系统交互时,这会很方便。

实际上,这意味着您可以传递一个打开的文件或StringIO/BytesIO流对象来打开或保存演示文稿,如下所示:

python 复制代码
f = open('foobar.pptx')
prs = Presentation(f)
f.close()

# or

with open('foobar.pptx') as f:
    source_stream = StringIO(f.read())
prs = Presentation(source_stream)
source_stream.close()
...
target_stream = StringIO()
prs.save(target_stream)

好的,所以你已经打开了一个演示文稿,并且很确定你可以稍后把它保存在某个地方。

下一步是在那里放一张幻灯片...


五、使用幻灯片

演示文稿中的每张幻灯片都基于幻灯片布局。

创建新幻灯片时,您必须指定要使用的幻灯片布局,这并不奇怪。

让我们花一分钟时间了解一些关于幻灯片布局的事情,这样我们添加的幻灯片看起来就像我们想要的那样。


1、幻灯片布局基础

幻灯片布局就像幻灯片的模板。

幻灯片布局上的任何内容都可以在用它创建的幻灯片上"显示",幻灯片布局上的格式选择由幻灯片继承。

这是获得professional-looking演示文稿的一个重要功能,所有幻灯片的格式都是一致的。

每个幻灯片布局都以类似的方式基于幻灯片母版,因此您可以在幻灯片母版上做出演示文稿范围的格式决定,并在幻灯片布局上做出特定于布局的决定。

实际上可以有多个幻灯片母版,但我现在假装只有一个。通常会有。

PowerPoint附带的演示主题有大约九种幻灯片布局,名称如标题、标题和内容、仅标题和空白。

每个都有零个或多个占位符(大部分不是零)、可以放置标题的预格式化区域、多级项目符号、图像等。

稍后会详细介绍这些。

标准PowerPoint主题中的幻灯片布局始终以相同的顺序出现。

这允许将一个甲板上的内容粘贴到另一个甲板上,并与正确的新幻灯片布局连接:

  • 标题(演示文稿标题幻灯片)
  • 标题和内容
  • 节标题(有时称为Segue)
  • 两个内容(并排项目符号文本框)
  • 比较(每个并排内容框的相同但附加标题)
  • 标题而已
  • 空白
  • 带标题的内容
  • 带标题的图片

在python-pptx中,这些是prs.slide_layouts[0][0]prs.slide_layouts[8]

然而,没有规则他们必须按这个顺序出现,只是 一个约定,后面跟着PowerPoint提供的主题。

如果甲板 您正在使用的模板具有不同的幻灯片布局或在 不同的顺序,您必须计算幻灯片布局索引 你自己。

这很简单。

只需在PowerPoint的幻灯片母版视图中打开它 从零开始,从头开始倒数。

现在我们可以开始制作新的幻灯片了。


2、添加幻灯片

让我们使用标题和内容幻灯片布局;很多幻灯片都这样做:

python 复制代码
SLD_LAYOUT_TITLE_AND_CONTENT = 1

prs = Presentation()
slide_layout = prs.slide_layouts[SLD_LAYOUT_TITLE_AND_CONTENT]
slide = prs.slides.add_slide(slide_layout)

需要注意的几件事:

  • 使用像SLD_LAYOUT_TITLE_AND_CONTENT这样的"常量"值取决于您。
    如果您正在创建许多幻灯片,那么定义常量会很方便 读者更容易理解你在做什么。
    没有一套 这些内置在包裹中,因为它们不能保证适合 您正在使用的起始甲板。
  • prs.slide_layouts是包含在 演示文稿和列表语义学,至少对于项目访问,这是关于 目前你能做的就是收集。
    使用prs为 演示实例纯粹是传统的,但我喜欢并使用它 始终如一。
  • prs.slides是演示文稿中幻灯片的集合,也有 列出项目访问的语义学,len()处理它。
    请注意,该方法 添加幻灯片在幻灯片集合中,而不是演示文稿中。
    add_slide()()方法将新幻灯片附加到集合的末尾。
    在 写作的时间是添加幻灯片的唯一方法,但迟早 我希望有人想在中间插入一个,当他们发布时 一个功能请求,我希望我会添加一个insert_slide(idx, ...) 方法。

3、用幻灯片做其他事情

现在,添加幻灯片是幻灯片集合上的唯一操作。

在撰写本文时,在积压中删除幻灯片并将幻灯片移动到列表中的不同位置。

在一般情况下,将幻灯片从一个演示文稿复制到另一个演示文稿是非常困难的,所以在更多积压被烧毁之前,这可能不会发生。


六、了解形状

幻灯片上的几乎所有东西都是形状;我能想到的唯一能出现在非形状幻灯片上的是幻灯片背景。

根据你的计数,有六到十种不同类型的形状。

我将解释一些你需要理解如何使用它们的一般形状概念,然后我们将直接进入特定类型的工作。

从技术上讲,有六种且只有六种不同类型的形状可以放置在幻灯片上:

  • 自动形状

    这是一个规则的形状,如矩形、椭圆或方块箭头。

    它们有各种各样的预设形状,大约有180个不同的形状。

    自动形状可以有填充和轮廓,并且可以包含文本。

    一些自动形状有调整,例如,您可以拖动小黄色菱形来调整圆角矩形的角有多圆。

    输入框也是一个自动形状,一个矩形,默认情况下没有填充和轮廓。

  • 图片

    光栅图像,如照片或剪贴画,在PowerPoint中被称为图片。

    它是自己的形状,具有不同于自动塑造的行为。

    请注意,自动形状可以有图片填充,其中图像"显示通过"作为形状的背景,而不是填充颜色或渐变。

    这是另一回事。

    但是很酷。

  • graphic frame

    这是包含表格、图表、智能艺术图或媒体剪辑的容器的技术名称。

    您不能单独添加其中一个,当您添加图形对象时,它只会显示在文件中。

    您可能不需要了解更多关于这些的信息。

  • group shape

    在PowerPoint中,可以对一组形状进行分组,允许将它们作为一个单元进行选择、移动、调整大小,甚至填充。

    当您对一组形状进行分组时,会创建一个组形状来包含这些成员形状。

    除了在选择组时通过它们的边界框之外,您实际上看不到这些。

  • line/connector

    线条不同于自动形状,因为它们是线性的。

    有些线可以连接到其他形状,并在另一个形状移动时保持连接。

    这些也不支持,所以我对它们了解不多。

    不过,我最好尽快拿到这些,它们看起来会很方便。

  • 内容部分

    实际上,我对这些是什么只有最模糊的概念。

    它与在演示文稿中嵌入"外国"XML(如SVG)有关。

    我很确定PowerPoint本身对这些没有任何作用。

    我的策略是忽略它们。

    到目前为止运行良好。


至于现实生活中的形状,有以下九种:

  • shape shapes - 带有填充和轮廓的自动形状
  • 文本框-无填充和无轮廓的自动形状
  • 占位符-可以出现在幻灯片布局或母版上并在使用该布局的幻灯片上继承的自动形状,允许添加采用占位符格式的内容
  • line/connector - 如上所述
  • 图片 --- 如上所述
  • 表 --- 那个行和列的东西
  • 图表------饼图、折线图等。
  • smart art --- 尚不支持,但如果存在则保留
  • 媒体剪辑-视频或音频

访问幻灯片上的形状

每个幻灯片都有一个形状树来保存它的形状。

它被称为树,因为它在一般情况下是分层的;形状树中的节点可以是一个组形状,它本身可以包含形状,并且具有与形状树相同的语义学。

对于大多数用途,形状树具有列表语义学。

您可以像这样访问它:

python 复制代码
shapes = slide.shapes

我们将在接下来的几节中看到更多的形状树。


七、使用自动形状(AutoShapes)

自动形状是规则的形状。

正方形、圆形、三角形、星星之类的东西。

有182种不同的自动形状可供选择。

其中120种有调整"手柄",您可以使用它们来改变形状,有时甚至是戏剧性的。

许多形状类型共享一组公共属性。

我们将在这里介绍其中的许多,因为其中一些形状只是AutoShape的一种特殊形式。


1、添加自动形状

以下代码添加了一个圆角矩形形状,一英寸见方,位于幻灯片左上角一英寸处:

python 复制代码
from pptx.enum.shapes import MSO_SHAPE

shapes = slide.shapes
left = top = width = height = Inches(1.0)
shape = shapes.add_shape(
    MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height
)

请参阅MSO_AUTO_SHAPE_TYPE枚举页面以获取所有182个自动 形状类型。


2、理解英语度量单位

在前面的示例中,我们将位置和尺寸值设置为 表达式Inches(1.0)

那是关于什么的?

在内部,PowerPoint以英制公制单位(EMU)存储长度值。

这个术语可能值得快速谷歌一下,但简短的故事是EMU是一个整数长度单位,914400到英寸。

Office文档中的大多数长度都存储在EMU中。

914400有一个很大的优点,即它可以被许多常见因素均匀整除,例如,允许英寸和厘米之间的精确转换。

作为一个整数,它可以在序列化和跨平台上精确表示。

正如您可能想象的那样,直接在EMU中工作很不方便。

为了使其更容易,python-pptx提供了值类型的集合,以允许轻松规范和转换为方便的单位:

python 复制代码
>>> from pptx.util import Inches, Pt
>>> length = Inches(1)
>>> length
914400
>>> length.inches
1.0
>>> length.cm
2.54
>>> length.pt
72.0
>>> length = Pt(72)
>>> length
914400

更多详细信息可在pptx. util的API留档中找到


3、形状位置和尺寸

所有形状在幻灯片上都有一个位置和一个大小。

通常,创建形状时会指定位置和大小。

位置和大小也可以从现有形状中读取并更改:

python 复制代码
>>> from pptx.enum.shapes import MSO_SHAPE
>>> left = top = width = height = Inches(1.0)
>>> shape = shapes.add_shape(
>>>     MSO_SHAPE.ROUNDED_RECTANGLE, left, top, width, height
>>> )
>>> shape.left, shape.top, shape.width, shape.height
(914400, 914400, 914400, 914400)
>>> shape.left.inches
1.0
>>> shape.left = Inches(2.0)
>>> shape.left.inches
2.0

4、填充

自动形状在其外边缘周围有一个轮廓。

出现在该轮廓内的内容称为形状的填充。

最常见的填充类型是纯色。

一个形状也可以用渐变、图片、图案填充(例如交叉阴影),或者可能没有填充(透明)。

使用颜色时,可以将其指定为特定的RGB值或主题调色板中的颜色。

因为选项太多,填充的API有点复杂。

此代码将形状的填充设置为红色:

python 复制代码
>>> fill = shape.fill
>>> fill.solid()
>>> fill.fore_color.rgb = RGBColor(255, 0, 0)

这会将其设置为在工具栏调色板中显示为"口音1-25%暗"的主题颜色:

python 复制代码
>>> from pptx.enum.dml import MSO_THEME_COLOR
>>> fill = shape.fill
>>> fill.solid()
>>> fill.fore_color.theme_color = MSO_THEME_COLOR.ACCENT_1
>>> fill.fore_color.brightness = -0.25

这会将形状填充设置为透明,或在PowerPoint UI中调用的"无填充":

python 复制代码
>>> shape.fill.background()

如您所见,第一步是通过调用指定所需的填充类型 填充上的相应方法。

这样做实际上会改变属性 在填充对象上可用。

例如,引用.fore_color在 填充对象在调用其.background()方法后会引发一个 例外:

python 复制代码
>>> fill = shape.fill
>>> fill.solid()
>>> fill.fore_color
<pptx.dml.color.ColorFormat object at 0x10ce20910>
>>> fill.background()
>>> fill.fore_color
Traceback (most recent call last):
  ...
TypeError: a transparent (background) fill has no foreground color

5、线

AutoShape的轮廓也可以格式化,包括设置其颜色、宽度、破折号(实线、破折号、虚线等)、线条样式(单、双、粗细等)、端盖、连接类型等。

在编写时,可以使用python-pptx设置颜色和宽度:

python 复制代码
>>> line = shape.line
>>> line.color.rgb = RGBColor(255, 0, 0)
>>> line.color.brightness = 0.5  # 50% lighter
>>> line.width = Pt(2.5)

主题颜色也可以用于线条:

python 复制代码
>>> line.color.theme_color = MSO_THEME_COLOR.ACCENT_6

Shape.line具有.color 属性。

这本质上是一个快捷方式 对于:

python 复制代码
>>> line.fill.solid()
>>> line.fill.fore_color

这对于线条格式很有意义,因为形状轮廓最常设置为纯色。

例如,需要直接访问填充以将线条设置为透明:

python 复制代码
>>> line.fill.background()

线宽

形状轮廓还具有读/写宽度属性:

python 复制代码
>>> line.width
9525
>>> line.width.pt
0.75
>>> line.width = Pt(2.0)
>>> line.width.pt
2.0

6、调整自动形状

许多汽车形状都有调整。

在幻灯片中,这些显示为黄色的小钻石,你可以拖动来改变形状的外观。

通过程序处理它们有点繁琐,但是如果你有耐心把它们做好,你可以非常精确地实现一些显著的效果。


形状调整概念

在尝试进行认真的调整之前,有几个概念值得掌握。

首先,调整是特定的自动形状类型。

每个自动形状都有零到八个调整。

他们每个人做什么是任意的,取决于形状设计。

从概念上讲,调整是指南,在许多方面就像您可以在PowerPoint UI和其他绘图应用程序中对齐的浅蓝色。

这些不显示,但它们以类似的方式运行,每个都定义了一部分形状将对齐的x或y值,改变形状的比例。

调整值是大整数,每个值基于100,000的标称值。

调整的有效值与形状的宽度或高度成正比。

因此,x坐标调整的值为50,000对应于形状宽度的一半;y坐标调整的值为75,000对应于形状高度的3/4。

调整值可以是负数,通常表示坐标在形状左上角(原点)的左侧或上方。

值也可以受到限制,这意味着它们的有效值不能超出规定的范围。

例如,在实践中,这对应于一个点不能延伸到形状的左侧之外。

花些时间在PowerPoint中调整形状是时候了 很好地建立了对他们行为的直觉。

你可能还想要 安装opc-diag,以便您可以查看以下XML值 由不同的调整产生,作为开发您的 调整码。

以下代码使用其调整格式化标注形状:

python 复制代码
callout_sp = shapes.add_shape(
    MSO_SHAPE.LINE_CALLOUT_2_ACCENT_BAR, left, top, width, height
)

# get the callout line coming out of the right place
adjs = callout_sp.adjustments
adjs[0] = 0.5   # vert pos of junction in margin line, 0 is top
adjs[1] = 0.0   # horz pos of margin ln wrt shape width, 0 is left side
adjs[2] = 0.5   # vert pos of elbow wrt margin line, 0 is top
adjs[3] = -0.1  # horz pos of elbow wrt shape width, 0 is margin line
adjs[4] = 3.0   # vert pos of line end wrt shape height, 0 is top
a5 = adjs[3] - (adjs[4] - adjs[0]) * height/width
adjs[5] = a5    # horz pos of elbow wrt shape width, 0 is margin line

# rotate 45 degrees counter-clockwise
callout_sp.rotation = -45.0

八、理解占位符

直观地说,占位符是一个预先格式化的容器,可以将内容放入其中。

通过为其内容提供预先设置的格式,它将许多格式选择交到模板设计者手中,同时允许最终用户专注于实际内容。

这加快了演示开发过程,同时鼓励从同一模板创建的幻灯片的视觉一致性。

虽然它们典型的最终用户行为相对简单,但结构 支持他们操作的更复杂。

此页面是为那些 想更好地了解占位符子系统的架构和 也许不太容易对其有时令人困惑的行为感到困惑。

如果你 不要关心他们为什么工作,只是想知道如何与他们合作,你可以 想要跳到以下页面使用占位符


1、占位符是一个形状

占位符是形状的一个正交类别,也就是说多个形状类型可以是占位符。

特别是,自动形状(p: sp元素)、图片(p:pic元素)和图形框架(p:graph icFrame)形状类型可以是占位符。

组形状(p:grpSp)、连接器(p:cxnSp)和内容部分(p:contentPart)形状不能是占位符。

图形框架占位符可以包含表格、图表或SmartArt。


2、占位符类型

有18种占位符。

  • 标题、中心标题、副标题、正文

    这些占位符通常出现在仅包含文本的传统"单词图表"上,通常组织为标题和一系列要点。

    所有这些占位符都只能接受文本。

  • 内容

    此多用途占位符最常用于幻灯片正文。

    未填充时,它会显示6个按钮,允许插入表格、图表、SmartArt、图片、剪贴画或媒体剪辑。

  • 图片,剪贴画

    它们都允许插入图像。

    剪贴画占位符上的插入按钮会显示剪贴画库而不是图像文件选择器,但除此之外,它们的行为相同。

  • 图表、表格、智能艺术

    这三个允许插入相应类型的丰富图形内容。

  • 媒体剪辑

    允许插入视频或录音。

  • 日期、页脚、幻灯片编号

    这三个出现在大多数幻灯片母版和幻灯片布局中,但与大多数用户预期的行为不同。

    这些也通常出现在笔记母版和讲义母版上。

  • 表头

    仅在笔记母版和讲义母版上有效。

  • 垂直主体、垂直对象、垂直标题

    用于垂直方向的语言,例如日语。


3、未填充与已填充

幻灯片上的占位符可以为空或填充。

这在图片占位符中最为明显。

当未填充时,占位符会显示可自定义的提示文本。

当为空时,丰富的内容占位符还会显示一个或多个内容插入按钮。

纯文本占位符在输入文本的第一个字符时进入"填充"模式,在删除文本的最后一个字符时返回到"未填充"模式。

内容丰富的占位符在插入图片等内容时进入填充模式,在删除该内容时返回到未填充模式。

为了删除填充的占位符,形状必须删除两次。

第一次删除会删除内容并将占位符恢复到未填充模式。

额外的删除会删除占位符本身。

已删除的占位符可以通过重新应用布局来恢复。


4、Placholders继承

出现在幻灯片上的占位符只是整个占位符机制的一部分。

占位符行为需要三种不同类别的占位符形状;存在于幻灯片母版上的占位符,幻灯片布局上的占位符,以及最终出现在演示文稿幻灯片上的占位符。

这三类占位符参与属性继承层次结构,要么作为继承者,要么作为继承者,或者两者兼而有之。

母版上的占位符形状仅为继承者。

相反,幻灯片上的占位符形状仅为继承者。

幻灯片布局上的占位符既是幻灯片母版占位符的可能继承者,也是链接到该布局的幻灯片占位符上的占位符的继承者。

布局从其主版继承的方式与幻灯片从其布局继承的方式不同。

布局占位符从共享相同类型的主版占位符继承。

幻灯片占位符从具有相同idx值的布局占位符继承。

通常,所有格式属性都继承自"父"占位符。

这包括位置和大小以及填充、行和字体。

任何直接应用的格式都会覆盖相应的继承值。

直接应用的格式可以在重新应用布局时删除。


5、词汇表

  • 占位符形状

    幻灯片上继承自布局占位符的形状。

  • 布局占位符

    幻灯片布局上占位符形状的简写名称,幻灯片上的特定占位符从中继承形状属性

  • 主占位符

    幻灯片母版上布局占位符继承自的占位符形状(如果有)。


六、使用占位符

占位符可以使添加内容变得容易得多。

如果您曾经从头开始向幻灯片添加新文本框,并注意到需要进行多少调整才能达到您想要的方式,您就会明白为什么。

占位符位于正确的位置,具有正确的字体大小、段落对齐方式、项目符号样式等。

等等。

基本上,您只需单击并输入一些文本,就可以得到一张幻灯片。

占位符也可以用来在幻灯片上放置内容丰富的对象。

图片、表格或图表都可以插入占位符,从而获得占位符的位置和大小,以及它的某些格式属性。


1、访问占位符

每个占位符也是一个形状,因此可以使用 shapes幻灯片的属性。

然而,在寻找 一个特定的占位符,placeholders属性可以使 事情更容易。

访问已知占位符的最可靠方法是通过其 idx值。

占位符的idx值 是幻灯片布局占位符的整数键,它继承属性 从。

因此,它在幻灯片的整个生命周期内保持稳定,并将 使用该布局创建的任何幻灯片都是如此。

查看幻灯片上的占位符并挑选出您想要的占位符通常很容易:

python 复制代码
>>> 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

...然后,手头有已知索引,可以直接访问它:

python 复制代码
>>> slide.placeholders[1]
<pptx.parts.slide.PicturePlaceholder object at 0x10d094590>
>>> slide.placeholders[2].name
'Text Placeholder 3'

占位符集合上的项目访问类似于 字典而不是列表。

虽然上面使用的键是整数, 查找的是idx值,而不是序列中的位置。

如果提供 value与其中一个占位符的idx值不匹配, KeyError将被引发。

idx值不一定是连续的。

通常,内置幻灯片中占位符的idx值 布局(随PowerPoint提供的布局)将介于0和5之间。

标题 占位符将始终有idx0(如果存在)和任何其他 占位符将按从上到下和从左到右的顺序排列。

用户在PowerPoint中添加到幻灯片布局的占位符将收到 idx值从10开始。


2、识别和表征占位符

占位符在某些方面的行为与其他形状不同。

在 特别是,它的shape_type属性的值是 无条件地MSO_SHAPE_TYPE.PLACEHOLDER,无论是什么类型的 它是占位符或它包含的内容类型:

python 复制代码
>>> prs = Presentation()
>>> slide = prs.slides.add_slide(prs.slide_layouts[8])
>>> for shape in slide.shapes:
...     print('%s' % shape.shape_type)
...
PLACEHOLDER (14)
PLACEHOLDER (14)
PLACEHOLDER (14)

要了解更多信息,有必要检查占位符的内容 placeholder_format属性所有形状都有这个 属性,但在非占位符形状上访问它会引发ValueError

可以使用is_placeholder属性来确定 形状是否是占位符:

python 复制代码
>>> for shape in slide.shapes:
...     if shape.is_placeholder:
...         phf = shape.placeholder_format
...         print('%d, %s' % (phf.idx, phf.type))
...
0, TITLE (1)
1, PICTURE (18)
2, BODY (2)

占位符的另一种不同方式是它从布局占位符继承其位置和大小。

如果占位符的位置和大小发生更改,则会覆盖此继承。


3、将内容插入占位符

某些占位符类型具有专门的内容插入方法。

在当前版本中,图片、表格和图表占位符具有内容插入方法。

文本可以像文本插入自动形状一样插入标题和正文占位符。


PicturePlaceholder.insert_picture()

图片占位符有一个insert_picture() 方法:

python 复制代码
>>> 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
PICTURE (18)
>>> picture = placeholder.insert_picture('my-image.png')

对图片占位符的引用在其 insert_picture()方法被调用。

这是 因为插入图片的过程代替了原来的p: sp 带有包含图片的新p: pic元素的XML元素。

任何尝试 调用后使用原始占位符引用将引发 AttributeError

新的占位符是 insert_picture() 使用相同的idx密钥进行集合。

以这种方式插入的图片按比例拉伸并裁剪为 填充整个占位符。

当长宽比 源图像和占位符是相同的。

如果图片更高 在方面比占位符,它的顶部和底部被裁剪均匀以适应。

如果它更宽,它的左右两边被平均裁剪。

裁剪可以 使用占位符上的裁剪属性进行调整,例如 crop_bottom.


TablePlaceholder.insert_table()

表占位符有一个insert_table()方法。

内置模板没有包含表格占位符的布局,所以这 示例假定一个名为 having-table-placeholder.pptx具有打开idx 10的表占位符 它的第二张幻灯片布局:

python 复制代码
>>> prs = Presentation('having-table-placeholder.pptx')
>>> slide = prs.slides.add_slide(prs.slide_layouts[1])
>>> placeholder = slide.placeholders[10]  # idx key, not position
>>> placeholder.name
'Table Placeholder 1'
>>> placeholder.placeholder_format.type
TABLE (12)
>>> graphic_frame = placeholder.insert_table(rows=2, cols=2)
>>> table = graphic_frame.table
>>> len(table.rows), len(table.columns)
(2, 2)

以这种方式插入的表具有原始占位符的位置和宽度。

它的高度与行数成正比。

与所有丰富内容插入方法一样,对表占位符的引用 在其insert_table()方法为 调用。

这是因为插入丰富内容的过程取代了 原始p: spXML元素与一个新元素,一个p:graph icFrame在这里 case,包含丰富的内容对象。

任何尝试使用原始 调用后的占位符引用将引发AttributeError

新的 占位符是insert_table()调用的返回值,也可以是 使用原始idx键从占位符集合中获取,10 在这种情况下。

的返回值insert_table() 方法是一个PlaceholderGraphicFrame对象,它具有所有属性 和GraphicFrame对象的方法以及特定于 占位符。

插入的表格包含在图形框架中,可以 使用其table属性获取。


ChartPlaceholder.insert_chart()

图表占位符有一个insert_chart()方法。

内置在python-pptx中的演示模板没有包含图表的布局 占位符,因此此示例假定起始演示文稿名为 having-chart-placeholder.pptx具有打开idx 10的图表占位符 它的第二张幻灯片布局:

python 复制代码
>>> from pptx.chart.data import ChartData
>>> from pptx.enum.chart import XL_CHART_TYPE

>>> prs = Presentation('having-chart-placeholder.pptx')
>>> slide = prs.slides.add_slide(prs.slide_layouts[1])

>>> placeholder = slide.placeholders[10]  # idx key, not position
>>> placeholder.name
'Chart Placeholder 9'
>>> placeholder.placeholder_format.type
CHART (12)

>>> chart_data = ChartData()
>>> chart_data.categories = ['Yes', 'No']
>>> chart_data.add_series('Series 1', (42, 24))

>>> graphic_frame = placeholder.insert_chart(XL_CHART_TYPE.PIE, chart_data)
>>> chart = graphic_frame.chart
>>> chart.chart_type
PIE (5)

以这种方式插入的图表具有原始占位符的位置和大小。

注意insert_chart()的返回值是 一个PlaceholderGraphicFrame对象,而不是图表本身。

一个PlaceholderGraphicFrame对象具有以下所有属性和方法 一个GraphicFrame对象以及那些特定于占位符的对象 插入的图表包含在图形框架中,可以使用 它的chart属性。

与所有丰富内容插入方法一样,对图表占位符的引用 在其insert_chart()方法为 调用。

这是因为插入丰富内容的过程取代了 原始p: spXML元素与一个新元素,一个p:graph icFrame在这里 case,包含丰富的内容对象。

任何尝试使用原始 调用后的占位符引用将引发AttributeError

新的 占位符是insert_chart()调用的返回值,也可以是 使用原始idx键从占位符集合中获取,10 在这种情况下。


4、设置幻灯片标题

几乎所有幻灯片布局都有一个标题占位符,任何基于布局的幻灯片在应用布局时都会继承该占位符。

访问幻灯片的标题是一项常见操作,并且在形状树上有一个专用属性:

python 复制代码
title_placeholder = slide.shapes.title
title_placeholder.text = 'Air-speed Velocity of Unladen Swallows'

七、处理文本

自动形状和表格单元格可以包含文本。

其他形状不能。

无论其容器如何,文本始终以相同的方式操作。

文本存在于三个级别的层次结构中:

形状中的所有文本都包含在其文本框架中。

文本框架具有垂直对齐、边距、换行和自动拟合行为、旋转角度、一些可能的3D视觉特征,并且可以设置为将其文本格式化为多列。

它还包含一系列段落,即使为空,也始终包含至少一个段落。

段落具有行距、前空格、后空格、可用的项目符号格式、制表符、大纲/缩进级别和水平对齐方式。

段落可以为空,但如果包含任何文本,则该文本包含在一次或多次运行中。

运行可以提供字符级别的格式,包括字体、大小和颜色、可选的超链接目标URL、粗体、斜体和下划线样式、删除线、字距调整和一些大写样式(如所有大写)。

让我们一个接一个地运行这些。

仅显示当前版本中可用的功能。


1、访问文本框

如前所述,并非所有形状都有文本框架。

因此,如果您不确定并且不想捕获可能的异常,您需要在尝试访问它之前进行检查:

python 复制代码
for shape in slide.shapes:
    if not shape.has_text_frame:
        continue
    text_frame = shape.text_frame
    # do things with the text frame
    ...

2、访问段落

一个文本框架总是至少包含一个段落。

这会导致将多个段落放入一个形状的过程比人们可能喜欢的要笨拙一点。

例如,假设您想要一个包含三个段落的形状:

python 复制代码
paragraph_strs = [
    'Egg, bacon, sausage and spam.',
    'Spam, bacon, sausage and spam.',
    'Spam, egg, spam, spam, bacon and spam.'
]

text_frame = shape.text_frame
text_frame.clear()  # remove any existing paragraphs, leaving one empty one

p = text_frame.paragraphs[0]
p.text = paragraph_strs[0]

for para_str in paragraph_strs[1:]:
    p = text_frame.add_paragraph()
    p.text = para_str

3、添加文本

实际上,只有游程可以包含文本。为形状、文本框或段落上的 .text 属性分配字符串是将文本放置在这些对象包含的游程中的快捷方法。以下两个片段产生了相同的结果:

python 复制代码
shape.text = 'foobar'

# is equivalent to ...

text_frame = shape.text_frame
text_frame.clear()
p = text_frame.paragraphs[0]
run = p.add_run()
run.text = 'foobar'

4、应用文本帧级格式

以下将生成一个具有单个段落的形状,底部比顶部边距稍宽(这些默认值为0.05"),没有左边距,文本对齐顶部,并且关闭了换行。

此外,自动大小行为设置为调整形状的宽度和高度以适应其文本。

请注意,文本框架上设置了垂直对齐。

每个段落上设置了水平对齐:

python 复制代码
from pptx.util import Inches
from pptx.enum.text import MSO_ANCHOR, MSO_AUTO_SIZE

text_frame = shape.text_frame
text_frame.text = 'Spam, eggs, and spam'
text_frame.margin_bottom = Inches(0.08)
text_frame.margin_left = 0
text_frame.vertical_anchor = MSO_ANCHOR.TOP
text_frame.word_wrap = False
text_frame.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT

TextFrame的可能值TextFrame.auto_sizeTextFrame.vertical_anchor由枚举指定 MSO_AUTO_SIZEMSO_VERTICAL_ANCHOR分别。


5、应用段落格式

下面生成一个包含三个左对齐段落的形状,第一个段落下面的第二个和第三个缩进(如子项目符号):

python 复制代码
from pptx.enum.text import PP_ALIGN

paragraph_strs = [
    'Egg, bacon, sausage and spam.',
    'Spam, bacon, sausage and spam.',
    'Spam, egg, spam, spam, bacon and spam.'
]

text_frame = shape.text_frame
text_frame.clear()

p = text_frame.paragraphs[0]
p.text = paragraph_strs[0]
p.alignment = PP_ALIGN.LEFT

for para_str in paragraph_strs[1:]:
    p = text_frame.add_paragraph()
    p.text = para_str
    p.alignment = PP_ALIGN.LEFT
    p.level = 1

6、应用字符格式

字符级别的格式应用于运行级别,使用.font 属性。

以下格式为18pt Calibri Bold的句子并适用 主题颜色Accent 1。

python 复制代码
from pptx.dml.color import RGBColor
from pptx.enum.dml import MSO_THEME_COLOR
from pptx.util import Pt

text_frame = shape.text_frame
text_frame.clear()  # not necessary for newly-created shape

p = text_frame.paragraphs[0]
run = p.add_run()
run.text = 'Spam, eggs, and spam'

font = run.font
font.name = 'Calibri'
font.size = Pt(18)
font.bold = True
font.italic = None  # cause value to be inherited from theme
font.color.theme_color = MSO_THEME_COLOR.ACCENT_1

如果您愿意,您可以将字体颜色设置为绝对RGB值。

请注意,更改主题时不会改变颜色:

python 复制代码
font.color.rgb = RGBColor(0xFF, 0x7F, 0x50)

也可以通过提供目标URL将运行制作成超链接:

python 复制代码
run.hyperlink.address = 'https://github.com/scanny/python-pptx'

八、使用图表

python-pptx支持添加图表和修改现有图表。

支持3D类型以外的大多数图表类型。


1、添加图表

以下代码在新演示文稿中添加单系列柱形图:

python 复制代码
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')



2、有点定制东西

剩下的代码将省略我们已经看到的代码,只显示导入,例如,当它们第一次使用时,只是为了保持对新位的关注。

让我们创建一个多系列图表以用于这些示例:

python 复制代码
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


请注意,我们捕获了由 add_chart()graphic_frame,然后提取 图形框架中的图表对象使用其 chart属性。

我们需要图表参考来获取 到我们在接下来的步骤中需要的属性。

add_chart()方法不直接返回图表 对象。

那是因为图表本身不是一个形状。

相反,它是一个图形 (DrawingML)包含在图形框架形状中的对象 方式也是如此,也包含在图形框架形状中。


3、XY和气泡图

到目前为止,图表对自变量(粗略地说,X轴)使用一组离散的值。

当你的值属于一组定义明确的类别时,这些是完美的。

然而,有很多情况下,特别是在科学和工程中,自变量是一个连续的值,例如温度或频率。

这些在PowerPoint中得到XY(又名散点)图表的支持。

气泡图本质上是一个XY图表,其中标记大小用于反映一个附加值,有效地为图表添加了第三个维度。

因为自变量是连续的,一般来说,级数不 所有共享相同的X值。

这需要一些不同的数据 由不同的XyChartDataBubbleChartData对象,用于指定这些图表后面的数据 类型:

python 复制代码
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


气泡图的创建非常相似,每个指定气泡大小的数据点都有一个附加值:

python 复制代码
chart_data = BubbleChartData()

series_1 = chart_data.add_series('Series 1')
series_1.add_data_point(0.7, 2.7, 10)
series_1.add_data_point(1.8, 3.2, 4)
series_1.add_data_point(2.6, 0.8, 8)

chart = slide.shapes.add_chart(
    XL_CHART_TYPE.BUBBLE, x, y, cx, cy, chart_data
).chart



4、轴

让我们稍微改变一下类别和值轴:

python 复制代码
from pptx.enum.chart import XL_TICK_MARK
from pptx.util import Pt

category_axis = chart.category_axis
category_axis.has_major_gridlines = True
category_axis.minor_tick_mark = XL_TICK_MARK.OUTSIDE
category_axis.tick_labels.font.italic = True
category_axis.tick_labels.font.size = Pt(24)

value_axis = chart.value_axis
value_axis.maximum_scale = 50.0
value_axis.minor_tick_mark = XL_TICK_MARK.OUTSIDE
value_axis.has_minor_gridlines = True

tick_labels = value_axis.tick_labels
tick_labels.number_format = '0"%"'
tick_labels.font.bold = True
tick_labels.font.size = Pt(14)


好吧,这可能有点过分了。

但它让我们了解了我们可以用值和类别轴做的事情。

让我们撤消这部分,回到我们之前的版本。


5、数据标签

让我们添加一些数据标签,以便我们可以准确地看到每个条的值是多少:

python 复制代码
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


在这里,我们需要访问一个Plot对象来访问数据标签。

绘图就像一个子图表,包含一个或多个系列,并作为特定的图表类型绘制,如列或线。

对于组合了多种类型的图表,例如出现在柱形图顶部的折线图,需要进行这种区分。

像这样的图表将有两个绘图对象,一个用于显示为列的系列,另一个用于线条。

大多数图表只有一个绘图,python-pptx还不支持创建多绘图图表,但是您可以访问已经有它们的图表上的多个绘图。

在Microsoft API中,名称ChartGroup用于此对象。

当我学习MS Office图表时,我发现这个术语很长一段时间都令人困惑,所以我在python-pptx中选择了该对象的名称Plot。


6、Legend

图表上的图例通常很有用,可以为每个系列命名,并帮助读者区分哪个是哪个:

python 复制代码
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


不错!好吧,让我们试试其他图表类型。


7、折线图

折线图的添加方式与条形图或柱形图几乎相同 主要区别在于add_chart()调用中提供的图表类型:

python 复制代码
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


我在这里切换了类别和系列数据,以更好地适应折线图。

您可以看到"西部"区域的线被平滑成曲线,而其他两个区域的点与直线段相连。


8、饼图

饼图有点特别,因为它只有一个系列,没有任何轴:

python 复制代码
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



9、Odds & Ends

这应该足以让您开始将图表添加到您的 使用python-pptx进行演示。

API留档中有更多详细信息 图表在这里:图表


关于颜色

默认情况下,分配给图表中每个系列的颜色是主题颜色Accent 1到Accent 6,按此顺序排列。

如果您有六个以上的系列,则使用相同颜色的深色和浅色版本。

虽然可以为至少某些图表类型的数据点(条形、线条、饼图段等)分配特定颜色,但最好的开始策略是更改起始"模板"演示文稿中的主题颜色。


九、使用表

PowerPoint允许以表格形式(对齐的行和列)以相当灵活的方式呈现文本和数字。

PowerPoint表格的功能远不如Excel电子表格,而且肯定不如Microsoft Word中的表格强大,但它适用于大多数演示目的。


1、概念

有几个术语值得回顾,作为理解PowerPoint表格的基础:

  • 桌子

    表格是排列成对齐行和列的单元格矩阵。

    这种有序的排列使读者更容易理解相对大量的单个项目。

    它通常用于显示数字,但也可用于文本块。


  • 细胞

    表格中的单个内容"容器"。

    单元格有一个文本框,其中包含该内容。

    PowerPoint表格单元格只能包含文本。

    我不能保存图像、其他形状或其他表格。

    单元格具有背景填充、边框、边距和其他几个可以逐个单元格自定义的格式设置。

  • 在表中运行的并排单元格序列,所有单元格共享相同的顶部和底部边界。

  • 横跨表格高度的垂直单元格序列,所有单元格共享相同的左右边界。

  • 表格网格,也是单元格网格

    PowerPoint表格中的基础单元格是严格规则的。

    在一个3乘3的表格中,有9个网格单元格,每行3个,每列3个。

    合并单元格的存在可以掩盖单元格的一部分,但不会改变网格中单元格的数量。

    在python-pptx中,访问表格单元格总是通过单元格在单元格网格中的坐标,这可能不符合其在表格中的视觉位置(或缺乏视觉位置)。

  • 合并单元

    一个单元格可以水平、垂直或两者兼而有之地与相邻单元格"合并",从而使生成的单元格看起来和行为都像一个单元格,它跨越了以前由这些单元格占用的区域。


  • 合并源单元

    合并单元格中左上角的网格单元格具有某些特殊的行为 该单元格的内容是幻灯片上显示的内容;任何"跨越"的内容 单元格是隐藏的。

    在python-pptx中,可以使用 _Cell.is_merge_origin属性。

    这样的单元格可以报告 合并的单元格及其span_heightspan_width 属性,并且可以使用"取消合并"回其底层网格单元格 它的split()方法。

  • 跨细胞

    被合并的"占用"的合并源单元格以外的网格单元格 单元格称为跨单元格

    直观地说,合并源单元格"跨越" 其区域内的其他网格单元格。

    跨单元格可以用 它的_Cell.is_spanned属性。

    合并源单元格本身不是 一个跨越的细胞。


2、添加表

以下代码在新演示文稿中添加了一个3乘3的表格:

python 复制代码
>>> from pptx import Presentation
>>> from pptx.util import Inches

>>> # ---create presentation with 1 slide---
>>> prs = Presentation()
>>> slide = prs.slides.add_slide(prs.slide_layouts[5])

>>> # ---add table to slide---
>>> x, y, cx, cy = Inches(2), Inches(2), Inches(4), Inches(1.5)
>>> shape = slide.shapes.add_table(3, 3, x, y, cx, cy)

>>> shape
<pptx.shapes.graphfrm.GraphicFrame object at 0x1022816d0>
>>> shape.has_table
True
>>> table = shape.table
>>> table
<pptx.table.Table object at 0x1096f8d90>


有几件事要注意:

  • SlideShapes.add_table()返回包含表格的形状,而不是 表格本身。
    在PowerPoint中,表格包含在图形框架中 形状,如图表或SmartArt。
    您可以确定形状是否 包含一个使用其has_table属性的表 使用形状的表格访问table 财产。

3、将表插入表占位符

占位符允许您指定形状的位置和大小作为演示文稿"模板"的一部分,并在基于该模板创作演示文稿时将您选择的形状放入该占位符中。

这可以使演示文稿看起来更好,对象从一张幻灯片到另一张幻灯片出现在一致的位置。

占位符有不同的类型,其中之一是表格占位符。

表格占位符的行为与其他占位符相同,只是它只能接受表格的插入。

其他占位符类型接受文本项目符号或图表。

布局占位符和幻灯片占位符之间有一个微妙的区别。

布局占位符出现在幻灯片布局中,并定义从它"克隆"到使用该布局创建的每张幻灯片上的占位符的位置和大小。

只要您不调整幻灯片占位符的位置或大小,它就会从它派生的布局占位符继承它的位置和大小。

要将表格插入表格占位符,您需要一个包含表格占位符的幻灯片布局,并且您需要使用该布局创建幻灯片。

这些示例假设template.pptx中的第三张幻灯片布局包括一个表格占位符:

python 复制代码
>>> prs = Presentation('template.pptx')
>>> slide = prs.slides.add_slide(prs.slide_layouts[2])

访问表格占位符。

通常,访问占位符形状的最简单方法是知道它在幻灯片集合中的位置。

如果您始终使用相同的模板,它将始终显示在相同的位置:

python 复制代码
>>> table_placeholder = slide.shapes[1]

*插入一个表。

*通过调用其表将表插入占位符 insert_table() 行数和列数:

python 复制代码
>>> shape = table_placeholder.insert_table(rows=3, cols=4)

返回值是包含新表的GraphicFrame形状,而不是 表对象本身。

使用该table的属性 访问表对象的形状:

python 复制代码
>>> table = shape.table

包含形状控制位置和大小。

其他一切,如访问单元格及其内容,都是从表对象完成的。


4、访问单元格

表中的所有内容都在单元格中,因此获取对其中之一的引用是一个很好的起点:

python 复制代码
>>> cell = table.cell(0, 0)
>>> cell.text
''
>>> cell.text = 'Unladen Swallow'


单元格由其行、列坐标指定为从零开始的偏移量。

左上角的单元格位于行、列(0,0)。

与自动形状一样,单元格具有文本框架,并且可以包含分为段落和运行的任意文本。

任何所需的字符格式都可以单独应用于每次运行。

然而,通常单元格文本只是一个简单的字符串。

对于这些情况 读/写 _Cell.text属性可以是设置单元格的最快方法 内容。


5、合并单元格

通过指定两个对角线单元格来生成合并单元格。

合并后的单元格将占用该对角线指定的矩形区域中的所有网格单元格:


python 复制代码
>>> cell = table.cell(0, 0)
>>> other_cell = table.cell(1, 1)
>>> cell.is_merge_origin
False
>>> cell.merge(other_cell)
>>> cell.is_merge_origin
True
>>> cell.is_spanned
False
>>> other_cell.is_spanned
True
>>> table.cell(0, 1).is_spanned
True


要注意的几件事:

  • 合并后的单元格显示为单个单元格,该单元格占用指定矩形区域中其他网格单元格以前占用的空间。
  • 合并单元格的格式(背景颜色、字体等)取自合并源单元格,在本例中为表格的左上角单元格。
  • 合并单元格中的内容已迁移到合并源单元格中。
    该内容不再出现在跨网格单元格中(尽管您目前看不到这些内容)。
    每个单元格的内容在合并单元格中显示为单独的段落;它没有连接成单个段落。
    内容按原始单元格的从左到右、从上到下的顺序迁移。
  • 调用other_cell.merge(cell)将具有完全相同的效果 合并原点始终是指定矩形中左上角的单元格 区域。
    有四种不同的方法来指定给定的矩形区域 (两个对角线,每个都有两个顺序)。

6、取消合并单元格

合并的单元格可以通过调用 split()方法在其合并源单元格上。

调用 split()在不是合并原点的单元格上引发 ValueError

python 复制代码
>>> cell = table.cell(0, 0)
>>> cell.is_merge_origin
True
>>> cell.split()
>>> cell.is_merge_origin
False
>>> table.cell(0, 1).is_spanned
False


请注意,作为.合并()操作的一部分执行的内容迁移没有逆转。


7、一些可能很方便的片段

用例:合并单元格的查询表:

python 复制代码
def iter_merge_origins(table):
    """Generate each merge-origin cell in *table*.

    Cell objects are ordered by their position in the table,
    left-to-right, top-to-bottom.
    """
    return (cell for cell in table.iter_cells() if cell.is_merge_origin)

def merged_cell_report(cell):
    """Return str summarizing position and size of merged *cell*."""
    return (
        'merged cell at row %d, col %d, %d cells high and %d cells wide'
        % (cell.row_idx, cell.col_idx, cell.span_height, cell.span_width)
    )

# ---Print a summary line for each merged cell in *table*.---
for merge_origin_cell in iter_merge_origins(table):
    print(merged_cell_report(merge_origin_cell))

打印如下报告:

python 复制代码
merged cell at row 0, col 0, 2 cells high and 2 cells wide
merged cell at row 3, col 2, 1 cells high and 2 cells wide
merged cell at row 4, col 0, 2 cells high and 1 cells wide

用例:仅访问显示文本(未跨越)的单元格:

python 复制代码
def iter_visible_cells(table):
    return (cell for cell in table.iter_cells() if not cell.is_spanned)

用例:确定表是否包含合并的单元格:

python 复制代码
def has_merged_cells(table):
    for cell in table.iter_cells():
        if cell.is_merge_origin:
            return True
    return False

十、使用笔记幻灯片

幻灯片可以有与之关联的注释。

这些可能最常见于幻灯片"普通"视图中幻灯片下方的注释窗格中,其中可能会显示"单击以添加注释"。

每次幻灯片出现在主窗格中时,此处添加的注释都会出现。

它们也出现在演示者视图和笔记页面视图中,两者都可以从菜单中获得。

笔记可以包含丰富的文本,通常是项目符号、粗体、不同的字体大小和颜色等。

笔记页面视图比普通视图中的笔记窗格具有更强大的工具来编辑笔记文本。

在API和底层XML中,包含文本的对象称为笔记幻灯片。

这是因为在内部,笔记幻灯片实际上是幻灯片的一个特殊实例。

它包含形状,其中许多是占位符,并允许插入新形状,例如图片(可能是徽标)自动形状、表格和图表。

因此,使用笔记幻灯片非常像使用普通幻灯片。

每张幻灯片可以有零张或一张笔记幻灯片。

笔记幻灯片是在第一次使用时创建的,通常可能通过向幻灯片添加笔记文本来创建。

一旦创建,它就会保留,即使所有文本都被删除。


1、笔记Master

使用笔记母版(Master)作为模板创建新的笔记幻灯片。

在PowerPoint中新创建的演示文稿没有笔记母版。

第一次需要时,通常是在创建第一张笔记幻灯片时,根据PowerPoint内部预设默认值创建一个。

也可以通过进入笔记母版视图来创建一个,几乎可以肯定是通过编辑那里找到的母版来创建的(虽然还没有尝试过)。

演示文稿最多可以有一个笔记母版。

笔记母版控制笔记页面的外观和感觉,笔记页面可以在屏幕上查看,但实际上是为打印而设计的。

因此,如果您希望笔记页面打印输出看起来与默认值不同,您可以通过编辑笔记母版进行大量自定义。

您可以使用菜单上的视图>母版>笔记母版访问笔记母版编辑器(至少在我的版本上)。

使用python-pptx创建的笔记幻灯片将在您打开以创建演示文稿的演示文稿文件中具有笔记母版的外观和感觉。

创建时,某些占位符(幻灯片图像、笔记、幻灯片编号)会从笔记母版复制到新的笔记幻灯片上(如果它们尚未从母版中删除)。

这些"克隆"占位符从其相应的笔记母版占位符继承位置、大小和格式。

如果笔记幻灯片占位符的位置、大小或格式发生更改,则更改后的属性将不再被继承(但是,未更改的属性将继续被继承)。


2、笔记幻灯片基础

说够了,让我们展示一些代码。

假设您正在使用一张幻灯片,并且您想查看它是否有笔记幻灯片:

python 复制代码
>>> slide.has_notes_slide
False

好的,还没有。

很好。

让我们添加一些注释:

python 复制代码
>>> notes_slide = slide.notes_slide
>>> text_frame = notes_slide.notes_text_frame
>>> text_frame.text = 'foobar'

好吧,很简单。

让我们看看这里发生了什么:

  • slide.notes_slide给了我们笔记幻灯片。
    在这种情况下,它首先 根据笔记母版创建笔记幻灯片。
    如果没有笔记 主人,它也创造了那个。
    所以很多事情都可能发生在 你第一次打电话的场景,但是如果我们再打一次 它只是给我们返回对相同笔记幻灯片的引用,它 缓存,一旦检索到。
  • notes_slide.notes_text_frame给了我们TextFrame对象 包含实际的笔记。
    原因不只是 notes_slide.text_frame可能不止一个。
    什么 这是在幕后做的是找到占位符形状 包含注释(与幻灯片图像、标题、幻灯片编号相反, 等等)并给我们那个特定的文本框架。
  • 笔记幻灯片中的文本框架与普通幻灯片中的文本框架的工作原理相同。
    更准确地说,笔记幻灯片中形状上的文本框架的工作原理与 我们使用.text属性快速弹出一些文本 在那里。

使用文本框,您可以添加任意数量的文本,根据需要进行格式化。


3、笔记幻灯片占位符

到目前为止,我们还没有明确看到幻灯片母版上的形状。

很容易开始:

python 复制代码
>>> notes_placeholder = notes_slide.notes_placeholder

这个笔记占位符就像我们在后面看到的身体占位符。

您可以更改它的位置、大小和许多其他属性,以及通过它的文本框架获取它的文本。

您还可以访问其他占位符:

python 复制代码
>>> for placeholder in notes_slide.placeholders:
...   print placeholder.placeholder_format.type
...
SLIDE_IMAGE (101)
BODY (2)
SLIDE_NUMBER (13)

还有形状(占位符的超集):

python 复制代码
>>> for shape in notes_slide.shapes:
...   print shape
...
<pptx.shapes.placeholder.NotesSlidePlaceholder object at 0x11091e890>
<pptx.shapes.placeholder.NotesSlidePlaceholder object at 0x11091e750>
<pptx.shapes.placeholder.NotesSlidePlaceholder object at 0x11091e990>

在常见情况下,笔记幻灯片仅包含占位符。

但是,如果您在笔记幻灯片中添加了一个图像,例如,它也会显示出来。

请注意,如果您将该图像添加到笔记母版,也许是一个徽标,它将"直观地"出现在笔记幻灯片上,但不会作为笔记幻灯片形状集合中的形状出现。

相反,它在视觉上"继承"自笔记母版。


十一、用例

驱使我开始开发这个库的用例是自动化幻灯片的构建,这些幻灯片很难手工制作。

举个例子,考虑用一个特定部门的10张头像图像组成一张幻灯片的任务,照片旁边有这个人的名字和头衔。

在这样做了十几次并努力让所有的对齐和尺寸达到我对细节的关注满意的程度后,嗯,我的编码手指很痒。

不过,我认为,更广泛的应用将是非Windows服务器平台上的服务器端文档生成,Linux主要是我的预期。

在我的组织中,我发现人们对PowerPoint文档作为一种交流方式的需求似乎永不满足。

一旦一个人超越了项目经理的级别,解释比要点更长的文本的意愿似乎会迅速萎缩,PowerPoint成为一种日常媒介。

我想象过,能够为销售人员生成一个"演示就绪"的甲板可能很酷,其中包括他们只需点击几下即可在销售演示中使用的产品曲库的特定子集。

当你想出应用程序时,我很想听听它们。


十二、概念

python-pptx是完全面向对象的,一般来说你执行的任何操作 它将在一个对象上。

演示文稿的根对象是 Presentation

模块页面上提供了API详细信息,但这里有 一些基础知识让你开始,尤其是一些你可能会找到的关系 起初令人惊讶。

通过构建一个新的Presentation实例来加载演示文稿, 传入要加载的演示文稿的路径:

python 复制代码
from pptx import Presentation

path = 'slide-deck-foo.pptx'
prs = Presentation(path)

python-pptx还包含一个默认模板,如果你构建一个Presentation 没有路径的实例,基于该默认模板的演示文稿是 加载。

当你想快速开始时,这可能很方便,而且大部分 此留档中的示例使用默认模板。

python 复制代码
# start with default presentation
prs = Presentation()

请注意,目前在python-pptx中模板和演示文稿之间没有区别,就像在PowerPoint®客户端中一样,只有演示文稿。

要为演示文稿使用"模板",您只需创建一个包含您想要的所有样式、徽标和布局的演示文稿,删除所有幻灯片(如果合适的话,可以保留一些幻灯片),然后加载它作为您的起始位置。


1、幻灯片母版

演示文稿有一个幻灯片母版列表和一个幻灯片列表。

让我们从讨论幻灯片母版开始。

有些人(我确实有)感到惊讶的一个事实是,一个演示文稿文件可以有多个幻灯片母版。

根据我的经验,找到使用此功能的演示文稿并不常见,但它是完全支持的。

我唯一一次看到这种情况发生是当"外国"演示文稿中的幻灯片被粘贴到另一个卡组中时;如果您希望另一个卡组的格式和背景保留在粘贴的幻灯片上,幻灯片母版及其幻灯片布局需要随附。

因此,演示文稿需要维护一个幻灯片母版列表,而不仅仅是一个,即使99%的时间你只使用一个。

为了让99%的情况更容易一些,您可以参考第一个幻灯片母版,就好像它是唯一的一个一样:

python 复制代码
prs = Presentation()
slide_master = prs.slide_masters[0]
# is equivalent to
slide_master = prs.slide_master

2、幻灯片布局

另一个可能令人惊讶的事实是幻灯片布局属于幻灯片母版,而不是直接属于演示文稿,因此通常您必须通过幻灯片母版访问幻灯片布局。

由于这与上述99%的情况相同,属于第一张幻灯片母版的幻灯片布局也可以通过语法糖直接从演示文稿中访问:

python 复制代码
prs = Presentation()
title_slide_layout = prs.slide_masters[0].slide_layouts[0]
# is equivalent to:
title_slide_layout = prs.slide_layouts[0]

3、幻灯片

演示文稿中的幻灯片属于演示文稿对象,并且是 使用slides属性访问:

python 复制代码
prs = Presentation(path)
first_slide = prs.slides[0]

3.1 添加幻灯片

添加幻灯片是通过调用add_slide()方法来完成的 slides的属性。

必须通过幻灯片布局 in以指定新幻灯片应采用的布局:

python 复制代码
prs = Presentation()
title_slide_layout = prs.slide_layouts[0]
new_slide = prs.slides.add_slide(title_slide_layout)

2024-08-29(四)

相关推荐
转世成为计算机大神13 分钟前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
宅小海32 分钟前
scala String
大数据·开发语言·scala
小喵要摸鱼34 分钟前
Python 神经网络项目常用语法
python
qq_3273427335 分钟前
Java实现离线身份证号码OCR识别
java·开发语言
锅包肉的九珍36 分钟前
Scala的Array数组
开发语言·后端·scala
心仪悦悦39 分钟前
Scala的Array(2)
开发语言·后端·scala
yqcoder1 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
baivfhpwxf20231 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
许嵩661 小时前
IC脚本之perl
开发语言·perl
长亭外的少年1 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin