python-pptx 将自定义属性添加到 pptx 文件

问题描述 投票:0回答:1

我正在尝试使用 python-pptx 库向 pptx 文件添加自定义属性。我能够添加但无法保存文件。

使用 Python 3.10.12 Databricks 运行时:13.3 LTS

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.opc.constants import RELATIONSHIP_TYPE AS RT
from pptx.oxml.ns import nsdecls
from pptx.oxml import parse_xml

pptx = Presentation()
first_slide_layout = pptx.slide_layouts[0]

slide = pptx.slides.add_slide(first_slide_layout)

slide.shapes.title.text = "Created by Python-pptx"

pptx.save("databricks/driver/test.pptx")
####-----> until here code works.

## Below part of adding custom properties does not work.

def add_custom_properties(ppt, name, value):
        custom_property_xml = f'<properties xmlns = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties">'\
                     f'<property name="{name}" type="string">{value}</property>'\
                      '</properties>'
        custom_property = parse_xml(custom_property_xml)

        ppt.part.package.relate_to(custom_property, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties')

# Below command does not return any error.
add_custom_properties(pptx, "test_key", "test_key_value")

# while saving throws an error.
pptx.save("/databricks/driver/aaa.pptx")

错误:

file
可以是文件路径或打开用于写入字节的类文件对象。

有人可以帮我理解这段代码有什么问题吗?

python-3.x azure-databricks python-pptx
1个回答
0
投票

除了所有简单的语法错误和错误的文件路径之外,这段代码看起来好像任何人工智能都从其他代码片段中猜出了它。不,AI到现在还不能编程。

Package.relate_to
需要一个与之相关的包部件,而不是
lxml.etree
,因为
parse_xml
返回。

这种关系并不是事情的全部。首先需要创建一个包部件。 Python-pptx 目前不支持自定义属性部分。所以默认的pptx-template中没有这样的包部分。因此它必须使用

PartFactory
创建。

此外,

Properties
元素的 XML 也是错误的。有关示例和说明,请参阅在文字处理文档中设置自定义属性。这适用于文字处理文档,但也适用于演示幻灯片。

以下代码适用于我,并创建一个具有三个自定义属性集的

aaa.pptx

from pptx import Presentation

presentation = Presentation()
first_slide_layout = presentation.slide_layouts[0]

slide = presentation.slides.add_slide(first_slide_layout)

slide.shapes.title.text = 'Created by Python-pptx'

presentation.save('./test.pptx')
####-----> until here code works.

## Below part of adding custom properties works too now.

from pptx.opc.constants import (
    RELATIONSHIP_TYPE,
    CONTENT_TYPE,
)
from pptx.opc.packuri import PackURI
from pptx.opc.package import PartFactory

def add_custom_properties(presentation, name, value, value_type):
    contains_custom_property = False
    for part in presentation.part.package.iter_parts():
        if part.partname == '/docProps/custom.xml':
            custom_property_part = part
            contains_custom_property = True
            
    pid = 2    
    if not contains_custom_property:
        custom_property_xml = '<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">'
        custom_property_xml += f'<property fmtid="{{D5CDD505-2E9C-101B-9397-08002B2CF9AE}}" pid="{pid}" name="{name}">'
        custom_property_xml += f'<vt:{value_type}>{value}</vt:{value_type}>'
        custom_property_xml += '</property>'
        custom_property_xml += '</Properties>'
        
        custom_property_pack_uri = PackURI('/docProps/custom.xml')
        custom_property_content_type = CONTENT_TYPE.OFC_CUSTOM_PROPERTIES
        custom_property_part = PartFactory(custom_property_pack_uri, custom_property_content_type, presentation.part.package, custom_property_xml.encode('utf-8'))

        presentation.part.package.relate_to(custom_property_part, RELATIONSHIP_TYPE.CUSTOM_PROPERTIES)
    else:
        custom_property_xml = custom_property_part.blob.decode('utf-8')
        custom_property_xml = custom_property_xml[:-13]
        
        pid = 2 + custom_property_xml.count('<property')
        
        custom_property_xml += f'<property fmtid="{{D5CDD505-2E9C-101B-9397-08002B2CF9AE}}" pid="{pid}" name="{name}">'
        custom_property_xml += f'<vt:{value_type}>{value}</vt:{value_type}>'
        custom_property_xml += '</property>'    
        custom_property_xml += '</Properties>'
        custom_property_part.blob = custom_property_xml.encode('utf-8')

add_custom_properties(presentation, "test_key", "test_key_value", "lpwstr")
add_custom_properties(presentation, "number", "1234", "i4")
add_custom_properties(presentation, "date", "2024-08-06", "filetime")

# while saving not throws any error.
presentation.save('./aaa.pptx')
© www.soinside.com 2019 - 2024. All rights reserved.