使用 openpyxl 模块写入电子表格会创建损坏的电子表格,如何使用 zipfile 模块修复?

Posted

技术标签:

【中文标题】使用 openpyxl 模块写入电子表格会创建损坏的电子表格,如何使用 zipfile 模块修复?【英文标题】:Using openpyxl module to write to spreadsheet creates a damaged spreadsheet, how to fix with zipfile module? 【发布时间】:2017-01-29 19:26:20 【问题描述】:

我有一个使用openpyxl 写入电子表格的程序。执行程序后,单元格按预期填充,但电子表格已损坏。 Excel 修复了电子表格,然后我可以再次查看它。

import openpyxl
from openpyxl import load_workbook
amounts, row = [1, 2, 3, 4, 5], 2
book = load_workbook("output.xlsx")
sheet = book.active

for i, value in enumerate(amounts):
    sheet.cell(column=i+1, row=row, value=value)  
print ("Sheet updating complete.")
book.save("output.xlsx")

我尝试使用 Microsoft 的 Open XML SDK Productivity Tool 来比较好文件和坏文件,并注意到缺少 styles.xml。我尝试使用从另一个问题中获得的以下源代码复制它,但它并没有解决我的问题。

import zipfile
with zipfile.ZipFile('outputcopy.xlsx', 'r') as zgood:
    styles_xml = zgood.read('xl/styles.xml')
with zipfile.ZipFile('output.xlsx', 'a') as zbad:
    zbad.writestr('xl/styles.xml', styles_xml)

我可以从 Excel 生成的修复日志中确认问题出在xl/styles.xml。我需要将此 xml 文件从好副本复制到坏副本。

如何复制xl/styles.xml 文件,以便程序可以在不损坏output.xlsx 的情况下运行?

我已再次尝试解决此问题。万一styles.xml 无法从其他 Excel 文件中复制;我在book.save("output.xlsx") 之前从output.xlsx 打开了styles.xml。保存后,我从保存语句之前获取styles.xml,并编写它。不幸的是,这并没有改变任何东西,我仍然收到损坏的 Excel 文件。通过这次尝试,我的测试代码如下所示:

import openpyxl
import zipfile

from openpyxl import load_workbook
amounts, indexValue, row = [1, 2, 3, 4, 5], 0, 2
book = load_workbook("output.xlsx")
sheet = book.active

for i, value in enumerate(amounts):
    sheet.cell(column=i+1, row=row, value=value)  
print ("Sheet updating complete.")

with zipfile.ZipFile('output.xlsx', 'r') as zgood:
    styles_xml = zgood.read('xl/styles.xml')

book.save("output.xlsx")

with zipfile.ZipFile('output.xlsx', 'a') as zbad:
    zbad.writestr('xl/styles.xml', styles_xml)

我已尝试另存为全新的 Excel 文件,但仍然遇到同样的问题。我尝试使用zip fileoutput.xlsx 打开并写入新保存的文件,但仍然没有结果。

import openpyxl
import zipfile
from openpyxl import load_workbook

amounts, indexValue, row, cell = [1, 2, 3, 4, 5], 0, 2, "A2"
book = load_workbook("output.xlsx")
sheet = book.active

while indexValue != 5:
    sheet[cell] = amounts[indexValue]
    indexValue += 1
    cell = chr(ord(cell[0]) + 1) + str(cell[1])
print ("Sheet updating complete.")

book.save("test.xlsx")

with zipfile.ZipFile('output.xlsx', 'r') as zgood:
    styles_xml = zgood.read('xl/styles.xml')
with zipfile.ZipFile('test.xlsx', 'a') as zbad:
    zbad.writestr('xl/styles.xml', styles_xml)

虽然我已经解决了这个问题,但值得注意的是,这个问题似乎只在加载工作簿时出现。我用电子表格创建了另一个程序,它创建了一个工作簿,而不是加载它。因此,电子表格不会保存损坏的。

【问题讨论】:

您使用的是什么版本的 Microsoft Excel?我正在使用 MS Excel 2010,使用您的示例没有显示错误。 @Brian 我正在使用最新版本的 Microsoft Excel,2016。我尝试在 OS X 和 Windows 10 上打开 Excel 文件。附带说明,Apple 的 Numbers 似乎能够打开到文件非常好。 【参考方案1】:

在确认问题出在styles.xml 之后,我确定问题很可能与书写单元格的样式格式有关。通过使用openpyxl 模块中的styles,我已经解决了这个问题。

我声明了一个变量,在本例中为fontStyle,并设置了所有的样式设置:

fontStyle = Font(name="Calibri", size=12, color=colors.BLACK)

在向每个单元格写入amounts 时,我还使用fontStyle 设置这些单元格的样式:

sheet[cell].font = fontStyle

完成的代码,如下所示:

import openpyxl
from openpyxl import load_workbook
from openpyxl.styles import colors
from openpyxl.styles import Font, Color

fontStyle = Font(name="Calibri", size=12, color=colors.BLACK)
amounts, indexValue, cell = [1, 2, 3, 4, 5], 0, "A2"
book = load_workbook("output.xlsx")
sheet = book.active

while indexValue != 5:
    sheet[cell] = amounts[indexValue]
    sheet[cell].font = fontStyle
    indexValue += 1
    cell = chr(ord(cell[0]) + 1) + str(cell[1])

print ("Sheet updating complete.")
book.save("output.xlsx")

我相信这行得通,因为书写方法没有默认样式设置。这可以解释为什么在使用 Open XML SDK 生产力工具时缺少styles.xml。修复后再次检查此 Excel 文件后,我可以确认 styles.xml 不再丢失。

文件保存后不再损坏,可以再次正常打开。此外,我现在能够执行此脚本以再次写入 Excel 文件,而无需打开和关闭来修复它。

请注意,我还更改了原始循环的循环 - 作为我解决问题的尝试之一。这对最终结果没有影响——这完全取决于所写单元格的样式。

这并不能完全回答使用zipfile 专门解决问题的问题,但它确实解决了问题。

【讨论】:

以上是关于使用 openpyxl 模块写入电子表格会创建损坏的电子表格,如何使用 zipfile 模块修复?的主要内容,如果未能解决你的问题,请参考以下文章

python处理Excel表格--写入Excel表格

python处理Excel表格--写入Excel表格

Openpyxl 保存损坏/不可读的文件。没有报错,只是shell重启

不在电子表格中从头开始写入。 Excel VBA。

python 使用openpyxl来写数据到excel表格

Python之openpyxl模块的使用