当使用xlrd阅读包含公式的单元格值时,返回0.0。

14

我试图读取单元格的值,比如 E5,在 Excel 表格中 E5 包含一个公式 '=(A29 - A2)'。我使用以下代码,但它返回 0.00 而不是实际值 1.440408。有没有什么方法可以解决这个问题?我想打印出正确的值。请帮我解决这个问题。谢谢。

book = xlrd.open_workbook('Test.xlsx')
first_sheet = book.sheet_by_index(0)
particular_cell_value = (first_sheet.cell_value(4,4))
print(particular_cell_value)

看起来你在 first_sheet.cell_value(2, 2) 中获取了 C3 的值(如果 cell_value 的参数是基于1的,则为 D4)? - neoascetic
很抱歉,我只使用了(4,4)。我为了测试已经更改了它,并在这里给出了错误的信息。 - Ambi
我不介意在Python中使用任何Excel解析器来获得正确的结果。我也尝试过openpyxl和win32comclient,但它们都没有正确地返回结果。 :-( - Ambi
1
+1,因为我之前也遇到了同样的问题,但始终未找到解决方案。 - 6160
2个回答

21
Excel文件独立存储公式和值。如果文件是直接由Excel保存的,则Excel会同时写入公式和值。然而,由其他软件(如xlwt、OpenPyXL和XlsxWriter)生成的文件仅写入公式。这是因为没有保证第三方软件包能够完全按照Excel内置函数相同的方式进行计算。因此,建议(实际上是来自Microsoft本身)是让第三方软件包编写公式,将值设置为零,并设置全局“自动重新计算”标志(因此,如果在Excel中打开文件,Excel将自动计算所有公式结果)。
XlsxWriter在其write_formula()方法的文档中详细说明了这一点。
XlsxWriter不会计算公式的值,而是将值0作为公式结果存储。然后它在XLSX文件中设置一个全局标志,表示打开文件时应重新计算所有公式和函数。这是Excel文档和电子表格应用程序通常推荐的方法。但是,一些没有计算公式功能的应用程序(例如Excel Viewer或某些移动应用程序)只会显示0结果。
如果您真的想在那里放置一个值和公式,则可以按照其说明编写。该值可以是任何您选择的值,不一定是Excel计算的相同值。截至本文撰写时,xlwt和OpenPyXL都不支持此功能。
因此,在读取Excel文件方面,自然情况下,xlrd将选择0,除非同时也写入了结果。您会注意到,当文件最后由Excel保存时,xlrd总是拾取正确的结果。如果使用XlsxWriter写入结果,则它还将拾取结果(可能正确,也可能不正确)。

你救了我的一天...谢谢! - dtar
2
打开了Excel文件,保存后,现在它可以正常工作了!谢谢! - Oren Yosifon

0

一个值为零的单元格和一个空单元格之间存在差异。在openpyxl中测试此内容,您必须检查TYPE_NULL并检查None的值,因为TYPE_NULL和TYPE_STRING使用相同的值“s”。这对我来说似乎是一个错误。也许openpyxl将来会选择一个唯一的TYPE_NULL值。

def use_openpyxl():
    import openpyxl
    print ("Using openpyxl:")
    wb = openpyxl.load_workbook('cell_formula_test.xlsx')
    ws = wb.get_sheet_by_name('Sheet1')
    for row in ws.rows:
        for cell in row:
            if (cell.data_type == openpyxl.cell.Cell.TYPE_NULL) and (cell.value == None):
                continue
            print ("  %s:%s:%s" % (cell.address, cell.data_type, cell.value))

在xlrd中,cell_type确实对空单元格具有唯一的类型,因此检查更加直接。
def use_xlrd():
    import xlrd
    print ("Using xlrd:")
    wb = xlrd.open_workbook('cell_formula_test.xlsx')
    ws = wb.sheet_by_name('Sheet1')
    for i in range(ws.nrows):
        for j in range(ws.ncols):
            if ws.cell_type(i, j) != xlrd.XL_CELL_EMPTY:
                print ("  (%d, %d):%s:%s" % (i, j, ws.cell_type(i, j), ws.cell_value(i, j)))

哦,我明白了。空单元格和零值之间有差别。特别是对于 xlrd,您可以通过 cell_type 属性检查这一点。我将重新设计这个示例来展示这一点。 - ChipJust
ж•°жҚ®пјҡж—¶й—ҙжҲі дәӢ件 ж—¶й—ҙе·®иҮӘдәӢ件1 20178.55447 дәӢ件1 0 д»ҺдәӢ件1еҲ°дәӢ件3 20178.64812 дәӢ件2 0.093647 0.1671 20178.67671 дәӢ件3 0.122242 д»ҺдәӢ件1еҲ°дәӢ件N 20178.72157 дәӢ件4 0.1671 0.559553 20179.08555 дәӢ件5 0.531082 20179.10126 дәӢ件6 0.54679 20179.11403 дәӢ件7 0.559553 - Ambi
使用xlrd: (0, 0):1:时间戳 (0, 1):1:事件 (0, 2):1:从事件1开始的时间 (1, 0):2:20178.554472 (1, 1):1:事件1 (1, 2):2:0.0 (1, 4):1:事件1中的事件3 (2, 0):2:20178.648119 (2, 1):1:事件2 (2, 2):2:0.0 (2, 4):2:0.0 (3, 0):2:20178.676714 (3, 1):1:事件3 (3, 2):2:0.0 (3, 4):1:事件1中的事件N (4, 0):2:20178.721572 (4, 1):1:事件4 (4, 2):2:0.0 (4, 4):2:0.0 (5, 0):2:20179.085554 (5, 1):1:事件5 (5, 2):2:0.0 (6, 0):2:20179.101262 (6, 1):1:事件6 (6, 2):2:0.0 (7, 0):2:20179.114025 (7, 1):1:事件7 (7, 2):2:0.0 - Ambi
我只需要E3和E5中的值。因此,目前我已通过更改写入Excel表格的方式来纠正问题。即我将差异存储在变量中,然后将其写入文件,而不是将公式写入表格。这使得xlrd能够从表格中读取该值。但如果已经有一个永久解决方案或者我们可以制定一个永久解决方案,那就更好了。 - Ambi
使用XLRD将公式写入Excel表格后,它在Excel中的样子是怎样的? - ChipJust
显示剩余6条评论

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