使用xlrd读取Excel文件

19

我遇到了读取Perl脚本编写的.xls文件的问题,但这个脚本并不受我的控制。文件中包含一些单元格格式和换行符。

filename = '/home/shared/testfile.xls'
book = xlrd.open_workbook(filename)
sheet = book.sheet_by_index(0)
for rowIndex in xrange(1, sheet.nrows):
    row = sheet.row(rowIndex)
这里抛出以下错误:
_locate_stream(Workbook): seen
    0  5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
   20  4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
172480= 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
172500  4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 2
172520  2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
173840= 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
173860  2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1
173880  1 1 1 1 1 1 1 1
Traceback (most recent call last):
  File "/home/shared/xlrdtest.py", line 5, in <module>
    book = xlrd.open_workbook(filename)
  File "/usr/local/lib/python2.7/site-packages/xlrd/__init__.py", line 443, in open_workbook
    ragged_rows=ragged_rows,
  File "/usr/local/lib/python2.7/site-packages/xlrd/book.py", line 84, in open_workbook_xls
    ragged_rows=ragged_rows,
  File "/usr/local/lib/python2.7/site-packages/xlrd/book.py", line 616, in biff2_8_load
    self.mem, self.base, self.stream_len = cd.locate_named_stream(qname)
  File "/usr/local/lib/python2.7/site-packages/xlrd/compdoc.py", line 393, in locate_named_stream
    d.tot_size, qname, d.DID+6)
  File "/usr/local/lib/python2.7/site-packages/xlrd/compdoc.py", line 421, in _locate_stream
    raise CompDocError("%s corruption: seen[%d] == %d" % (qname, s, self.seen[s]))
xlrd.compdoc.CompDocError: Workbook corruption: seen[2] == 4

我无法找到与CompDocError或工作簿损坏有关的任何信息,更不用说seen[2] == 4部分了。


“filename” 包含什么内容? - juankysmith
2
我是xlrd的作者。你正在运行哪个版本的xlrd?如果你不能在保密协议下发送给我一个perl编写的文件副本,那么最好的办法就是告诉我你的电子邮件地址,这样我可以向你发送一个调查脚本,它将显示你的文件结构(而不是内容)。 - John Machin
@JohnMachin 我遇到了同样的问题,能否请您提供一下调查脚本。 - sharafjaffri
@snurre 你有找到任何解决方案吗?我正在使用最新的xrld但是仍然出现同样的错误。 - sharafjaffri
不好意思,我放弃了,最终让脚本输出JSON数据。 - snurre
显示剩余5条评论
7个回答

14

根据pkm的评论(链接),问题出在复合文件二进制格式上。

#pip install OleFileIO-PL
import OleFileIO_PL
import pandas as pd

path = 'file.xls'
with open(path,'rb') as file:
    ole = OleFileIO_PL.OleFileIO(file)
    if ole.exists('Workbook'):
        d = ole.openstream('Workbook')
        x=pd.read_excel(d,engine='xlrd')
        print(x.head())

1
OleFileIO_PL现在被称为olefile - tricasse

10

+1 to Ramiel. 只需在compdoc.py文件中注释掉这些行即可(在xlrd 1.2.0版本中的425-427行)。

if self.seen[s]:
    print("_locate_stream(%s): seen" % qname, file=self.logfile);dump_list(self.seen, 20, self.logfile)
    raise CompDocError("%s corruption: seen[%d] == %d" % (qname, s, self.seen[s]))

我知道这是一个老问题,但我遇到了相同的错误,并注释掉了那些行以及这里提到的链接,但没有用。有人已经找到解决方案了吗? - Gustavo Rottgering
@GustavoRottgering:请查看@holymoly345的回答 - tricasse

9

这个回答的启发,但更加简单明了:

pd.read_excel接受xlrd.Book对象,因此您可以执行以下操作:

workbook = xlrd.open_workbook('file_name.xls', ignore_workbook_corruption=True)
excel = pd.read_excel(workbook)

7

[针对在读取XLS文件时遇到“Workbook corruption: seen[2] == 4”错误的pandas用户]

注意: xlrd不再支持除xls文件以外的任何格式,详情和替代方案请参见此答案

  1. 使用xlrd 2.0.0或更高版本:https://pypi.org/project/xlrd/

  2. 在您的一个__init__.py文件中添加自己的XLS引擎,该文件会自动加载。

from pandas.io.excel._xlrd import XlrdReader

class CustomXlrdReader(XlrdReader):

    def load_workbook(self, filepath_or_buffer):
        """Same as original, just uses ignore_workbook_corruption=True)"""
        from xlrd import open_workbook

        if hasattr(filepath_or_buffer, "read"):
            data = filepath_or_buffer.read()
            return open_workbook(file_contents=data, ignore_workbook_corruption=True)
        else:
            return open_workbook(filepath_or_buffer)


ExcelFile._engines['custom_xlrd'] = CustomXlrdReader
print('Monkey patching pandas XLS engines. See CustomXlrdReader')

如果要使用它,请在读取XLS文件时指定engine='custom_xlrd'

df = pd.read_excel(filepath, engine='custom_xlrd')

以下是 xlrd 测试时使用的损坏文件:

https://github.com/python-excel/xlrd/blob/master/tests/samples/corrupted_error.xls


错误:ignore_workbook_corruption=True 应该在两个分支中。 - Sergei

2

我的一个 .xls 文件出现了同样的错误(excel可以正常打开它们)。问题出现在 xlrdcompdoc.py 文件中。我猜测 Compdoc.seen 数组跟踪已读取的“FAT”扇区。在我的情况下,根目录 entry 读取块(SSCS)将所有这些扇区标记为已读,导致未来引发异常。你可以尝试找到扇区读取逻辑中的错误并为 xlrd 做出贡献:),或者只需注释掉引发异常的行,这很可能会解决你的问题(就像我一样),然后等待 xlrd 更新。


“等待xlrd更新” -> 这个更新从2013年到2019年的六年里都没有出现,对吧? - Andi Schroff

0

也许作为最后的办法,您可以尝试将 .xls 文件保存为 .csv 文件,然后再尝试读取它。

显然,您说您可以在 Excel 打开和关闭后打开它,所以这是相同的努力。

如果您真的想让脚本打开它们,那么如果您在 Windows 平台上使用 pywin32 从脚本中打开和关闭 Excel,并在同一步骤中打开和关闭文件。也许这样可以工作。(愚蠢但可能是一个解决方法)

例如(从这里偷来的

from win32com.client import Dispatch
xl = Dispatch('Excel.Application')
wb = xl.Workbooks.Open('C:\\Documents and Settings\\GradeBook.xls')

-1

testfile.xls -----> 另存为 ---> 格式 97-2003 --->testfile2.xlc

文件名 = '/home/shared/testfile2.xls'

确定


请详细说明您的答案。解释这个程序是做什么的。 - funie200

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