Python无法打开Excel文件

5
我在一台Debian GNU/Linux电脑上,使用Python 2.7.9进行工作。作为工作的一部分,我编写了Python脚本,可以读取各种格式的输入文件(如Excel、Csv、Txt),并将信息解析到更标准化的文件中。这不是我第一次打开或使用Excel文件。有一个特定的文件让我遇到了问题,我无法打开它。当我尝试使用xlrd(版本0.9.3)时,它给出了以下错误:
xlrd.open_workbook('sample.xls')

XLRDError: 不支持的格式或损坏文件:BOF不是工作簿/工作表:op = 0x0009 vers = 0x0002 strm = 0x000a build = 0 year = 0 -> BIFF21
我尝试自己调查此问题,在StackOverflow中找到了一些答案,但无论如何我都无法打开它。我发现的这个特定答案可能是问题所在(第二个解释),但它没有包括解决方法:https://dev59.com/MmQn5IYBdhLWcg3w36XV#16518707 一个能够将文件转换为csv/txt的工具也可以解决问题。
我已经尝试过以下内容:
  • xlrd
  • openpyxl
  • xlsx2csv(shell工具)
可在此处获取示例文件:https://ufile.io/r4m6j 顺便说一句,我可以使用LibreOffice Calc和MS Excel打开它,因此我最终可以通过这种方式将其更改为csv。问题是,我需要使用Python脚本完成所有操作。
提前感谢!

请再确认一下 - 这个文件在 Excel 中打开没有任何问题吗? - GSazheniuk
据我所知,是的,我可以打开它,单元格看起来正常,没有任何异常。 - francisco sollima
@franciscosollima 这个Excel文件是从哪里来的?如果你是从Windows环境中获取它,那么换行符可能会根据Unix标准进行“翻译”。你可以检查一下,将你的.xlsx文件重命名为.zip文件并尝试打开它。你应该能够打开它并提取文件而不会出现任何问题。 - GSazheniuk
@franciscosollima 有没有可能你能分享这个文件?你可以从中删除任何敏感信息。 - GSazheniuk
1
没关系,正在努力获取一个样本! - francisco sollima
显示剩余8条评论
9个回答

2

这似乎是一个微软问题。xls文件非常奇怪,也许你应该联系xlrd支持团队。

但我有一个疯狂的解决方法:xls2ods。虽然xls2csv不行(SiC!),但对我有效。

所以,首先安装catdoc:

$sudo apt-get install catdoc

然后将您的xls文件转换为ods格式,使用pyexcel_ods或您喜欢的其他工具打开ods文件。要使用pyexcel_ods,请先安装它,命令为pip install pyexcel_ods

import subprocess

from pyexcel_ods import get_data

file_basename = 'sample'

returncode = subprocess.call(['xls2ods', '{}.xls'.format(file_basename)])
if returnecode > 0:
    # consider to use subprocess.Popen if you need more control on stderr
    exit(returncode)

data = get_data('{}.ods'.format(file_basename))
print(data)

我得到了以下输出:
OrderedDict([(u'sample',
              [[u'labo',
                u'codfarm',
                u'farmacia',
                u'direccion',
                u'localidad',
                u'nom_medico',
                u'matricula',
                u'troquel',
                u'producto',
                u'cant_total']])])

在我的情况下,我不得不从pip安装pyexcel_ods,因为尽管成功从apt安装了catdoc,但它仍然找不到pyexcel_ods模块。尽管如此,它还是能够正常工作!非常感谢! - francisco sollima
很高兴能帮忙。是的,我没有注意到pyexcel_ods不是catdoc的一部分,因为pyexcel_ods只是解析ODS文档的示例。 - Shmygol

2

这里是一个我会使用的临时解决方案:

假设您在Debian上安装了LibreOffice,您可以使用以下命令将所有*.xls文件转换为*.csv格式:

import os 
os.system("libreoffice --headless --convert-to csv *.xls")
#or use os.call

...然后持续使用csv

或者,您可以在需要时仅使用try/except块转换受损文件:

import os 

try:
    xlrd.open_workbook('sample.xls')
except XLRDError:
    os.system("libreoffice --headless --convert-to csv sample.xls")
    # mycsv = open("sample.csv", "r")
    # for line in mycsv.readlines():
    #     ...
    #     ...

注意:运行脚本时请确保LibreOffice已关闭。

另外,还有其他工具可用于进行转换。这是其中一个(我没有测试过):https://github.com/dilshod/xlsx2csv


当我运行 libreoffice --headless --convert-to csv sample.xls(无论是从os.system还是从shell)时,没有任何文件被创建。也没有错误。它只是默默地结束并且什么都不做... - francisco sollima
当我在打开libreoffice时运行脚本时,对我也发生了同样的情况。你确定在尝试运行脚本时它已经关闭了吗? - snake_charmer
你说得对,它确实有效,是我的错。我会点赞的,但我仍然会接受@Trilliput的答案,因为它在我的特定情况下更简单易行!无论如何还是谢谢! - francisco sollima

0
如果你的目标是Windows系统,如果你已经安装了Excel,并且熟悉Excel VBA,那么你可以使用comtypes包来快速解决问题。

http://pythonhosted.org/comtypes/

您将通过其COM接口直接访问Excel。


如何使用这个包?你能否在答案中加入一个快速的脚本来实际打开我提供的文件吗?至少将其保存为另一种格式,比如 .csv... - francisco sollima
{btsdaf} - user5852223

0

这段代码使用comtypes包打开一个xls文件并将其另存为cvs文件:

import comtypes.client as cl
progId = "Excel.Application.15"
xl = cl.CreateObject(progId)
wb = xl.Workbooks.Open(r"C:\Users\aUser\Desktop\thermoList.xls")
wb.SaveAs(r"C:\Users\aUser\Desktop\thermoList.csv",FileFormat=6)
xl.DisplayAlerts = False
xl.Quit()

我无法使用已损坏的“sample.xls”进行测试。 您可以尝试使用另一个文件。 您可能需要根据您的Excel版本调整progId。


{btsdaf} - francisco sollima
{btsdaf} - francisco sollima

0

这是一个文件格式问题。我不确定它是什么类型的文件,但它不是Excel。我只是打开并将文件保存为sample2.xls名称,并比较了类型: enter image description here

你是如何创建这个文件的?


{btsdaf} - francisco sollima
无论如何,这不是Excel。询问数据提供者他是如何保存的。 - ChaosPredictor

0

您提供的文件已损坏,因此其他回答者无法测试并推荐一个好的解决方案。您发布的异常也证实了这一点。 作为解决方案,您可以尝试调试一些内容,请参考以下步骤:

  • 您提到了尝试使用xlrd库。请尝试执行以下命令检查您的xlrd模块是否是最新版本:

    Python 2.7.9

    >>> import xlrd
    
    >>> xlrd.__VERSION
    

如有需要,请更新到最新的官方版本

希望这有所帮助。


0

你的Excel也无法打开。正如yadayada所说,我认为这是数据源的问题。如果你真的想找出原因,我建议你问关于Excel而不是Python的问题。


0

如果你需要将单词作为字符串列表获取:

text_file = open("sample.xls", "r")
lines = text_file.read().replace(chr(200), '').replace(chr(0), '').replace(chr(1), '').replace(chr(5), '').replace(chr(2), '').replace(chr(3), '').replace(chr(4), '').replace(chr(6), '').replace(chr(7), '').replace(chr(8), '').replace(chr(9), '').replace(chr(10), '').replace(chr(12), '').replace(chr(15), '').replace(chr(16), '').replace(chr(17), '').replace(chr(18), '').replace(chr(49), '').replace('Arial', '')
for line in lines.split(chr(128)):
    print(line)

输出结果: {{link1:在此输入图像描述}}

{btsdaf} - francisco sollima
{btsdaf} - francisco sollima

-2

对我来说,任何xls或xlsx文件都一直可以正常工作:

def csv_from_excel(filename_xls, filename_csv):
    wb = xlrd.open_workbook(filename_xls, encoding_override='YOUR_ENCODING_HERE (f.e. "cp1251"')
    sh = wb.sheet_by_index(0)
    your_csv_file = open(filename_csv, 'wb')
    wr = unicodecsv.writer(your_csv_file)
    for rownum in xrange(sh.nrows):
        wr.writerow(sh.row_values(rownum))
    your_csv_file.close()

所以,我在将 Excel 文件转换为 CSV 格式之前不直接处理它们。也许这会对你有所帮助。


我遇到了相同的错误,调用 xlrd.open_workbook 是导致我复制上面错误的原因。 - francisco sollima

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接