Python Pptx 未正确捕获幻灯片母版名称
Python Pptx not capturing Slide Master Name properly
玩 Python PPTX,它似乎没有正确读取幻灯片母版名称。
你可以看到这里我重命名了幻灯片母版
它甚至会在尝试添加幻灯片时出现
但是,当我通过 pptx
加载演示文稿时,名称是 ''
。
In [14]: import pptx
In [15]: pres = pptx.Presentation("adsf.pptx")
In [16]: pres.slide_master.name
Out[17]: ''
也许我在幻灯片方面做错了什么。我很想知道。我正在使用 Office 2016。附带说明一下,我正在研究 xml,看起来幻灯片母版 xml 没有包含与 ooxml
中的名称属性相关的任何属性。但是主题 xml 确实如此。让我感到困惑。
感谢您的时间和努力
编辑:
毕竟我找到了我的解决方案并感谢@Scanny
import pptx
import re
from lxml import etree
# This causes pres.slide_master.layout.placeholder.name to be passed to pres.slide.placeholder
@property
def placeholder_name(self):
"""Name of the placeholder inherited from slide master"""
return self._inherited_value("name")
def Presentation(powerpoint=None):
"""
Return a |Presentation| object loaded from *pptx*, where *pptx* can be
either a path to a ``.pptx`` file (a string) or a file-like object. If
*pptx* is missing or ``None``, the built-in default presentation
"template" is loaded.
"""
if powerpoint is None:
powerpoint = pptx.api._default_pptx_path()
# get the package and not just the presentation package
package = pptx.package.Package.open(powerpoint)
# now extract the document
presentation_part = package.main_document_part
if not pptx.api._is_pptx_package(presentation_part):
tmpl = "file '%s' is not a PowerPoint file, content type is '%s'"
raise ValueError(tmpl % (powerpoint, presentation_part.content_type))
# the theme names are the slide master names
themes = (part for part in package.parts if re.search("^/ppt/theme/theme\d+\.xml$",part.partname))
theme_names = [etree.fromstring(theme.blob).get("name") for theme in themes]
# now get the presentation
presentation = presentation_part.presentation
# change the slide master names
for idx,sld_mstr in enumerate(presentation.slide_masters):
sld_mstr.name = theme_names[idx]
return presentation
pptx.Presentation = Presentation
pptx.shapes.placeholder._InheritsDimensions.placeholder_name = placeholder_name
In [2]: pres = pptx.Presentation("adsf.pptx")
In [3]: for sm in pres.slide_masters: print(sm.name)
my master
number 3
my second
In [4]: layout = pres.slide_masters[0].slide_layouts[0]
In [5]: layout.name
Out[5]: 'my master title slide layout'
In [6]: new_slide = pres.slides.add_slide(layout)
In [7]: new_slide.placeholders[0].name
Out[7]: 'Title 1'
In [8]: new_slide.placeholders[0].placeholder_name
Out[8]: 'Main Title'
In [9]: pres.save("test.pptx")
是的,这就是我要继续的方式,在 XML 中查找字符串“my master”,看看它出现在哪里。
PowerPoint 主题包括母版和布局,因此 UI 可以计算此 rename 操作以重命名主题,这可以从 UI perspective,就像你想保存这个主题,然后通过从列表中选择这个名称来使用它。
反向操作可能有意义,意思是使用 python-pptx
设置主名称,读回它以确认,然后查看它在 UI 中出现的位置,如果有的话.
您可以直接从演示文稿进入 presentation-part:
prs = Presentation(...)
presentation_part = prs._part
所有部分都有包参考,不用自己加载:
package = presentation_part._package
但您可能不需要它,因为您可以直接从演示部分进入演示主题(而不是 Notes-pages 主题等):
from pptx.opc.constants import RELATIONSHIP_TYPE as RT
theme_rels = [rel for rel in presentation_part.rels if rel.reltype == RT.THEME]
theme_parts = [presentation_part.related_parts[rel.rId] for rel in theme_rels]
然后只需将每个主题作为 XmlPart 加载,例如:
theme_parts = [
XmlPart.load(
part._partname,
part._content_type,
part._blob,
part._package,
)
for part in theme_parts
]
然后您可以在 theme_part._element
上获取主题 XML 文档的根,您可以在其上使用 lxml.etree._Element
方法来遍历该树,或者只获取根元素名称带有 theme_part._element.attribs["name"]
.
这只是记忆中的 aircode,但希望能给你足够的继续,一旦你到达那里,你就可以 post 工作代码。
如果你有的东西可以完成工作,那么一定要使用它,但这可能更直接,并且使用已经存在的实现,这样你就不必担心事情会出乎意料地出错:)
几乎所有的代码都在 pptx/opc/package.py
.
中
玩 Python PPTX,它似乎没有正确读取幻灯片母版名称。
你可以看到这里我重命名了幻灯片母版
它甚至会在尝试添加幻灯片时出现
但是,当我通过 pptx
加载演示文稿时,名称是 ''
。
In [14]: import pptx
In [15]: pres = pptx.Presentation("adsf.pptx")
In [16]: pres.slide_master.name
Out[17]: ''
也许我在幻灯片方面做错了什么。我很想知道。我正在使用 Office 2016。附带说明一下,我正在研究 xml,看起来幻灯片母版 xml 没有包含与 ooxml
中的名称属性相关的任何属性。但是主题 xml 确实如此。让我感到困惑。
感谢您的时间和努力
编辑:
毕竟我找到了我的解决方案并感谢@Scanny
import pptx
import re
from lxml import etree
# This causes pres.slide_master.layout.placeholder.name to be passed to pres.slide.placeholder
@property
def placeholder_name(self):
"""Name of the placeholder inherited from slide master"""
return self._inherited_value("name")
def Presentation(powerpoint=None):
"""
Return a |Presentation| object loaded from *pptx*, where *pptx* can be
either a path to a ``.pptx`` file (a string) or a file-like object. If
*pptx* is missing or ``None``, the built-in default presentation
"template" is loaded.
"""
if powerpoint is None:
powerpoint = pptx.api._default_pptx_path()
# get the package and not just the presentation package
package = pptx.package.Package.open(powerpoint)
# now extract the document
presentation_part = package.main_document_part
if not pptx.api._is_pptx_package(presentation_part):
tmpl = "file '%s' is not a PowerPoint file, content type is '%s'"
raise ValueError(tmpl % (powerpoint, presentation_part.content_type))
# the theme names are the slide master names
themes = (part for part in package.parts if re.search("^/ppt/theme/theme\d+\.xml$",part.partname))
theme_names = [etree.fromstring(theme.blob).get("name") for theme in themes]
# now get the presentation
presentation = presentation_part.presentation
# change the slide master names
for idx,sld_mstr in enumerate(presentation.slide_masters):
sld_mstr.name = theme_names[idx]
return presentation
pptx.Presentation = Presentation
pptx.shapes.placeholder._InheritsDimensions.placeholder_name = placeholder_name
In [2]: pres = pptx.Presentation("adsf.pptx")
In [3]: for sm in pres.slide_masters: print(sm.name)
my master
number 3
my second
In [4]: layout = pres.slide_masters[0].slide_layouts[0]
In [5]: layout.name
Out[5]: 'my master title slide layout'
In [6]: new_slide = pres.slides.add_slide(layout)
In [7]: new_slide.placeholders[0].name
Out[7]: 'Title 1'
In [8]: new_slide.placeholders[0].placeholder_name
Out[8]: 'Main Title'
In [9]: pres.save("test.pptx")
是的,这就是我要继续的方式,在 XML 中查找字符串“my master”,看看它出现在哪里。
PowerPoint 主题包括母版和布局,因此 UI 可以计算此 rename 操作以重命名主题,这可以从 UI perspective,就像你想保存这个主题,然后通过从列表中选择这个名称来使用它。
反向操作可能有意义,意思是使用 python-pptx
设置主名称,读回它以确认,然后查看它在 UI 中出现的位置,如果有的话.
您可以直接从演示文稿进入 presentation-part:
prs = Presentation(...)
presentation_part = prs._part
所有部分都有包参考,不用自己加载:
package = presentation_part._package
但您可能不需要它,因为您可以直接从演示部分进入演示主题(而不是 Notes-pages 主题等):
from pptx.opc.constants import RELATIONSHIP_TYPE as RT
theme_rels = [rel for rel in presentation_part.rels if rel.reltype == RT.THEME]
theme_parts = [presentation_part.related_parts[rel.rId] for rel in theme_rels]
然后只需将每个主题作为 XmlPart 加载,例如:
theme_parts = [
XmlPart.load(
part._partname,
part._content_type,
part._blob,
part._package,
)
for part in theme_parts
]
然后您可以在 theme_part._element
上获取主题 XML 文档的根,您可以在其上使用 lxml.etree._Element
方法来遍历该树,或者只获取根元素名称带有 theme_part._element.attribs["name"]
.
这只是记忆中的 aircode,但希望能给你足够的继续,一旦你到达那里,你就可以 post 工作代码。
如果你有的东西可以完成工作,那么一定要使用它,但这可能更直接,并且使用已经存在的实现,这样你就不必担心事情会出乎意料地出错:)
几乎所有的代码都在 pptx/opc/package.py
.