You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用openpyxl为Excel工作簿添加自定义属性同步至SharePoint

openpyxl 修改支持SharePoint同步的带空格自定义工作簿属性方案

你用VBA操作的ContentTypeProperties属于OOXML格式定义的自定义文档属性,和wb.properties下暴露的核心文档属性(标题、作者、主题等固定字段)是完全独立的两套存储体系:

  • 你之前用setattr、修改__dict__的写法只是给Python对象临时加了实例属性,根本不会被写入xlsx文件结构,自然无法同步到SharePoint。
  • 3.2.0b1测试版的自定义属性API还在调整,你遇到的add方法不存在是因为该方法最终没有合入正式发布版本,不需要继续在beta版上调试。

方案1:openpyxl 3.1.0+ 正式版实现(推荐)

3.1.0及之后的正式版已经完整支持自定义文档属性读写,不需要调用不存在的add方法,直接向custom_doc_props列表追加CustomProperty对象即可:

from openpyxl import load_workbook
from openpyxl.packaging.custom import CustomProperty

# 加载已有工作簿
wb = load_workbook(r"你的目标文件路径.xlsx")

# 可选:先移除同名旧属性,避免重复存储
wb.custom_doc_props = [
    prop for prop in wb.custom_doc_props 
    if prop.name not in ("Project Title", "Project Number")
]

# 新增/修改自定义属性,完全支持带空格的属性名
wb.custom_doc_props.append(CustomProperty(name="Project Title", value="hello"))
wb.custom_doc_props.append(CustomProperty(name="Project Number", value=12))

# 保存修改
wb.save(r"修改后文件保存路径.xlsx")

类型说明:属性值会自动匹配SharePoint字段类型:传str存为文本、传int/float存为数值、传bool存为是/否、传datetime对象存为日期时间,和VBA修改的行为完全一致,保存后的文件在SharePoint同步目录下会自动同步属性值。


方案2:openpyxl 3.0.x 旧版本兼容方案

如果受环境限制无法升级openpyxl版本,可以直接操作xlsx压缩包内的自定义属性底层XML文件实现需求,不需要依赖库的上层封装:

from openpyxl import load_workbook
from openpyxl.xml.functions import fromstring, tostring
import xml.etree.ElementTree as ET

wb = load_workbook(r"你的目标文件路径.xlsx")

# 注册自定义属性XML命名空间
CUSTOM_PROP_NS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"
VALUE_TYPE_NS = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"
ET.register_namespace("", CUSTOM_PROP_NS)
ET.register_namespace("vt", VALUE_TYPE_NS)

# 读取已有自定义属性配置,不存在则新建根节点
if "docProps/custom.xml" in wb._archive.namelist():
    custom_props_root = fromstring(wb._archive.read("docProps/custom.xml"))
else:
    custom_props_root = ET.Element(f"{{{CUSTOM_PROP_NS}}}Properties")

def set_custom_prop(prop_name: str, prop_value):
    # 先删除已存在的同名属性
    for exist_prop in custom_props_root.findall(f"{{{CUSTOM_PROP_NS}}}property[@name='{prop_name}']"):
        custom_props_root.remove(exist_prop)
    # 生成新属性ID(从2开始计数,ID1为系统预留)
    exist_pids = [int(p.get("pid")) for p in custom_props_root.findall(f"{{{CUSTOM_PROP_NS}}}property")]
    new_pid = str(max(exist_pids + [1]) + 1)
    # 写入属性节点
    prop_node = ET.SubElement(
        custom_props_root,
        f"{{{CUSTOM_PROP_NS}}}property",
        {"fmtid": "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", "pid": new_pid, "name": prop_name}
    )
    # 匹配值类型写入节点
    if isinstance(prop_value, str):
        val_node = ET.SubElement(prop_node, f"{{{VALUE_TYPE_NS}}}lpwstr")
        val_node.text = prop_value
    elif isinstance(prop_value, (int, float)):
        val_node = ET.SubElement(prop_node, f"{{{VALUE_TYPE_NS}}}r8")
        val_node.text = str(prop_value)
    elif isinstance(prop_value, bool):
        val_node = ET.SubElement(prop_node, f"{{{VALUE_TYPE_NS}}}bool")
        val_node.text = "true" if prop_value else "false"

# 调用方法设置目标属性
set_custom_prop("Project Title", "hello")
set_custom_prop("Project Number", 12)

# 将修改后的XML写回工作簿包
wb._archive.writestr(
    "docProps/custom.xml",
    tostring(custom_props_root, encoding="UTF-8", xml_declaration=True)
)
wb.save(r"修改后文件保存路径.xlsx")

其他说明

  • xlsxwriter作为只写模式的库,本身不支持读取修改已有文件,不适合当前编辑存量文件的场景。
  • 不要尝试修改核心属性wb.properties来实现自定义属性需求,核心属性是OOXML标准定义的固定字段,即使强行给Python对象添加属性,也不会被序列化写入文件。

内容的提问来源于stack exchange,提问作者likethevegetable

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 16:01:08