读取PHPExcel修改的.xls文件时xlrd崩溃

时间:2013-05-17 22:13:31

标签: php python phpexcel xlrd

我很难用PHP和python编辑一些Excel文件。

我最初使用PHPExcel在PHP中完成了所有操作,但我正在处理非常大的文件,并且当内存不足时PHPExcel崩溃了。所以我改用它来做一些使用PHP的工作,然后用python做其余的工作。

所以过程是:

  • 将xml发布到PHP脚本
  • 根据xml数据
  • 将行插入Excel(.xls)文件
  • 将(.xls)文件和xml数据传递给python脚本以填充电子表格
  • 离。 PHP调用python upload.py Example.xls data.xml
  • python脚本使用xlrd,xlwt和xlutils填充Excel文件

我遇到的问题是,如果python脚本修改了我手工创建的常规.xls文件,它就能完美运行。但是一旦PHP excel修改了Excel文件,python脚本就会产生以下错误:

_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 
100= 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 
120  4 4 4 4 4 4 4 4 4 4 4 4 4 3 2 2 
File "upload.py", line 63, in <module>
workbook_readonly = open_workbook(excel,formatting_info=True,on_demand=True)
File "/home/student/eamorde/public_html/dining/xlrd/__init__.py", line 435, in open_workbook
ragged_rows=ragged_rows,
File "/home/student/eamorde/public_html/dining/xlrd/book.py", line 87, in open_workbook_xls
ragged_rows=ragged_rows,
File "/home/student/eamorde/public_html/dining/xlrd/book.py", line 619, in biff2_8_load
cd.locate_named_stream(UNICODE_LITERAL(qname))
File "/home/student/eamorde/public_html/dining/xlrd/compdoc.py", line 390, in locate_named_stream
d.tot_size, qname, d.DID+6)
File "/home/student/eamorde/public_html/dining/xlrd/compdoc.py", line 418, in _locate_stream
raise CompDocError("%s corruption: seen[%d] == %d" % (qname, s, self.seen[s]))
xlrd.compdoc.CompDocError: Workbook corruption: seen[2] == 4

所以我挖掘了xlrd的源代码,发现产生错误的行:

def _locate_stream(self, mem, base, sat, sec_size, start_sid, expected_stream_size, qname, seen_id):
    # print >> self.logfile, "_locate_stream", base, sec_size, start_sid, expected_stream_size
    s = start_sid
    if s < 0:
        raise CompDocError("_locate_stream: start_sid (%d) is -ve" % start_sid)
    p = -99 # dummy previous SID
    start_pos = -9999
    end_pos = -8888
    slices = []
    tot_found = 0
    found_limit = (expected_stream_size + sec_size - 1) // sec_size
    while s >= 0:
        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]))

最后一行是提出异常的那一行:

raise CompDocError("%s corruption: seen[%d] == %d" % (qname, s, self.seen[s]))

任何人都能解释一下吗?该文件在Excel打开时没有损坏,但是xlrd似乎无法读取它。

我的PHP脚本执行以下操作(粗略草图):

$phpExcel = new PHPExcel();
$file = "MyFile.xls";
$reader = new PHPExcel_Reader_Excel5();
$phpExcel = $reader->load($file);
//(... insert rows based on xml)
$writer = new PHPExcel_Writer_Excel5();
$writer->save('MyFile.xls');
exec("python upload.py MyFile.xls data.xml");

如果有人知道为什么会发生这种情况,甚至更好地解决我的问题(PHPExcel内存问题),我们将不胜感激。

编辑:可以找到引发错误的文件的源代码here

编辑:我创建了一个示例,基本上取了我的excel文件并删除了任何识别信息。要自己试一试,请参阅要点here

2 个答案:

答案 0 :(得分:4)

我的一个.xls文件出现了同样的错误(excel可以打开它们,但是xlrd失败了)。我猜Compdoc.seen数组跟踪已经读过的“FAT”扇区。在我的情况下,根条目读取块(SSCS)获取标记为所见的所有扇区,导致将来异常提升。你可以尝试在读取逻辑的扇区中找到错误并为xlrd做贡献:)或者只是通过异常加注来注释这一行,这可能会解决你的问题(就像我的一样)并等待xlrd更新。

答案 1 :(得分:2)

对于需要远程服务数据的绑定中的任何人,它都是黑客,但在raise CompDocError("%s corruption: seen[%d] == %d" % (qname, s, self.seen[s]))中注释掉第419行(compdoc.py)似乎没问题。