使用Python向带VBA的Excel文件写入数据且保留全部原有内容的方案咨询
复杂XLSM文件仅修改单元格数据的Linux可行方案
openpyxl 对复杂 Excel 中的 ActiveX 控件、自定义形状、VBA 关联属性等非基础元素支持不全,保存时会丢弃无法识别的XML节点,所以会出现原文件8MB保存后仅5MB、功能损坏的问题,以下是两种可在Linux环境运行的可行方案:
方案1:基于LibreOffice后端的xlwings操作
该方案适配性最高,原生完整保留所有原文件元素,无需手动处理XML结构。
- 先安装依赖:
首先安装LibreOffice:sudo apt install libreoffice
再安装xlwings库:pip install xlwings - 示例代码:
import xlwings as xw # 启动无界面LibreOffice进程 with xw.App(visible=False, spec="libreoffice") as app: wb = app.books.open("Tool.xlsm") # 按需求修改单元格数据 wb.sheets["SomeSheet"].range("SomeCell").value = "SomeValue" # 保存后所有VBA、控件、格式、形状均完整保留 wb.save("Tool_filled.xlsm") wb.close()
方案2:标准库直接操作XLSM压缩包
该方案轻量无额外大型依赖,仅修改目标工作表对应XML,其余所有文件原封不动打包,不会改动任何原有内容。
示例代码:
import zipfile import os import shutil from xml.etree import ElementTree as ET TEMP_DIR = "temp_excel_decompress" # 解压原xlsm文件 os.makedirs(TEMP_DIR, exist_ok=True) with zipfile.ZipFile("Tool.xlsm", "r") as zf: zf.extractall(TEMP_DIR) # 修改目标工作表XML,示例修改Sheet1的对应单元格,可根据需求调整工作表路径 ws_xml_path = os.path.join(TEMP_DIR, "xl", "worksheets", "sheet1.xml") ns = {"main": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"} tree = ET.parse(ws_xml_path) root = tree.getroot() # 定位目标单元格修改值 for cell in root.iter("{%s}c" % ns["main"]): if cell.attrib.get("r") == "SomeCell": cell.find("{%s}v" % ns["main"]).text = "SomeValue" tree.write(ws_xml_path) # 重新打包为xlsm文件 with zipfile.ZipFile("Tool_filled.xlsm", "w", zipfile.ZIP_DEFLATED) as zf: for root_path, _, files in os.walk(TEMP_DIR): for file in files: full_path = os.path.join(root_path, file) arc_path = os.path.relpath(full_path, TEMP_DIR) zf.write(full_path, arc_path) # 清理临时文件 shutil.rmtree(TEMP_DIR)
注意:修改单元格时如果是公式、特殊格式,可根据XML节点规则调整修改逻辑,仅修改值不会影响其他节点内容
内容的提问来源于stack exchange,提问作者Kound
相关产品推荐
相关产品推荐

