Python XLWT尝试覆盖单元格的解决方法

19

使用Python模块xlwt,两次写入同一个单元格会引发错误:

Message File Name   Line    Position    
Traceback               
    <module>    S:\******** 
    write   C:\Python26\lib\site-packages\xlwt\Worksheet.py 1003        
    write   C:\Python26\lib\site-packages\xlwt\Row.py   231     
    insert_cell C:\Python26\lib\site-packages\xlwt\Row.py   150     
Exception: Attempt to overwrite cell: sheetname=u'Sheet 1' rowx=1 colx=12   

使用以下代码片段

def insert_cell(self, col_index, cell_obj):
        if col_index in self.__cells:
            if not self.__parent._cell_overwrite_ok:
                msg = "Attempt to overwrite cell: sheetname=%r rowx=%d colx=%d" \
                    % (self.__parent.name, self.__idx, col_index)
                raise Exception(msg) #row 150
            prev_cell_obj = self.__cells[col_index]
            sst_idx = getattr(prev_cell_obj, 'sst_idx', None)
            if sst_idx is not None:
                self.__parent_wb.del_str(sst_idx)
        self.__cells[col_index] = cell_obj

看起来代码中有一个 'raise' 引发了异常,这会停止整个进程。只删除 'raise' 一词就足以允许覆盖单元格吗?我欣赏 xlwt 的警告,但我认为 Pythonic 的方式是假设“我们知道我们正在做什么”。我不想在接触模块时破坏其他任何东西。

4个回答

60

问题在于xlwt默认禁用了工作表数据的覆盖。你需要显式地允许它,像这样:

worksheet = workbook.add_sheet("Sheet 1", cell_overwrite_ok=True)

1
+1 在这里有记录:http://groups.google.com/group/python-excel/browse_thread/thread/c0def68185c7b85e - mechanical_meat
1
谢谢您实际给出答案,比指向一个大致方向更方便... - araisbec
有人知道如何在不使用add_sheet的情况下使用它吗?我正在使用xlutils.copy中的copy复制电子表格以复制工作簿,然后使用get_sheet获取工作簿中的第一个工作表。当我在上述方法中传递参数时,我一直收到“意外的关键字参数”。 - turnip

5
尼德·B所写的是有价值的建议,但需要注意的是,由于xlwt是pyExcelerator的一个分支,“模块作者”并没有明确定义;卡洛扬·托多罗夫说得很对。以下是更多的建议:(1)请注意您引用的代码中的以下行:
if not self.__parent._cell_overwrite_ok:

在代码中搜索_cell_overwrite_ok,你应该会得出Kaloyan的结论。

(2) 在python-excel Google组上提问(并搜索档案)。

(3) 查看此网站,其中提供了指向Google组和教程的指针。

背景:问题是有些人不知道他们在做什么(至少有一种情况是很高兴被告知的),而xlwt从pyExcelerator继承的行为是盲目地为同一个单元格写入两个(或更多)记录,这不仅导致文件膨胀,而且还会引起混淆,因为Excel会抱怨并显示第一个写入的记录,而OpenOffice和Gnumeric则会默默地显示最后一个写入的记录。从共享字符串表中删除所有旧数据的痕迹,以便它不会浪费空间或(更糟糕的是)在文件中可见,真是太麻烦了。

整个事件的记录都在Google组中。教程包括一个关于覆盖单元格的部分。


谢谢提供链接和信息,非常有启发性。从中我得出结论,过度覆盖表仍然是一个坏主意,因为被覆盖的数据仍然存在于文件夹中。 - PPTim
1
如果你这样收集,你所收集的是错误的;请参考上面“Removing all trace...was [past tense]”或者阅读Adam Bernier给你的链接中的帖子,要么相信它,要么运行帖子中第三条信息中的6行脚本,使用字符/十六进制转储程序(或xlrd提供的runxlrd.py与biff_dump命令一起使用)检查输出文件,并注意到广告中没有原始数据的痕迹。 - John Machin

3

如果你:

  • 不想在构造函数中将整个工作表设置为可覆盖,且
  • 仍然需要逐个处理异常情况

...请尝试以下方法:

try:
    worksheet.write(row, col, "text")
except:
    worksheet._cell_overwrite_ok = True
    # do any required operations since we found a duplicate
    worksheet.write(row, col, "new text")
    worksheet._cell_overwrite_ok = False

1

你应该联系模块的作者。仅仅移除一个raise是不太可能有效的。我猜测这会导致后续出现其他问题。例如,后面的代码可能会假设任何给定的单元格只在中间表示中出现一次。


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