簡體   English   中英

Python openpyxl 保存 xlsm 文件在打開時出錯

[英]Python openpyxl saving xlsm file gets error when opening

我有一個腳本可以打開一個 xlsm 文件和一個 xlsx 文件。 它使用來自 xlsx 的數據修改 xlsm,然后保存 xlsm 文件。 當我在腳本運行后打開該 xlsm 文件時,出現圖像中顯示的錯誤。 在此處輸入圖片說明

該文件然后工作正常,但我收到如下所示的 XML 錯誤: 在此處輸入圖片說明

我正在使用的代碼是:

import openpyxl
destwb = openpyxl.load_workbook(filename="C:\\627 Data\\winphy\\071-000-022-00 627 data.xlsm", read_only=False, keep_vba=True)

.....Code.....

destwb.save(filename="C:\\627 Data\\winphy\\071-000-022-00 627 data2.xlsm")

我遇到了類似的事情,並通過拼湊很大程度上回收代碼從該解決方案的Joost這樣一個問題: 如何保存XLSM文件與宏,使用openpyxl

顯然,openpyxl 在打開和保存時不會讀取或保留 xslm 的所有魔術宏部分。 由於文件是 zip 格式,因此解決方案:

  • 將您的工作保存為 xlsx
  • 以zip格式打開原始xlsm並提取關鍵部分
  • 使用您保存的 xlsx 中的數據和上述關鍵部分創建一個新的 zip
  • 將其重命名為 xlsm

我拿了示例代碼,把它變成了 workbook.save() 的可用替代品,修復了一個丟失的文件(自原始解決方案以來可能是 Excel 更改),添加了 zip 壓縮並創建了一個備份文件。 願這做你需要的。

def saveXlsm(wb, xlsmname):
'''Some crazy workaround to fix what openpyxl cannot when recreating an xlsm file. 
   Use as replacement for workbook.save()
'''
import zipfile
from shutil import copyfile
from shutil import rmtree

# Unzip original and tmp into separate dirs
PAD = os.getcwd()
wb.save('tmp.xlsx')
with zipfile.ZipFile(xlsmname, 'r') as z:
    z.extractall('./xlsm/')
with zipfile.ZipFile('tmp.xlsx', 'r') as z:
    z.extractall('./xlsx/')
# copy pertinent left out macro parts into tmp
copyfile('./xlsm/[Content_Types].xml','./xlsx/[Content_Types].xml')
copyfile('./xlsm/xl/_rels/workbook.xml.rels','./xlsx/xl/_rels/workbook.xml.rels')
copyfile('./xlsm/xl/vbaProject.bin','./xlsx/xl/vbaProject.bin')
copyfile('./xlsm/xl/sharedStrings.xml','./xlsx/xl/sharedStrings.xml')
# create a new tmp zip to rebuild the xlsm
z = zipfile.ZipFile('tmp.zip', 'w', zipfile.ZIP_DEFLATED)
# put all the parts back into the new Frankenstein
os.chdir('./xlsx')
for root, dirs, files in os.walk('./'):
        for file in files:
            z.write(os.path.join(root, file))
z.close()
os.chdir(PAD)
# humanize Frankenstein
bakname = xlsmname + '.bak'
if os.access(bakname, os.W_OK):
    os.remove(bakname)
os.rename(xlsmname, bakname)
os.rename('tmp.zip', xlsmname)
#clean
rmtree('./xlsm/')
rmtree('./xlsx/')
os.remove('./tmp.xlsx')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM