Openpyxl:操纵细胞值

时间:2013-07-08 07:00:01

标签: python-3.x typeerror openpyxl

我正在尝试从Excel工作表中提取单元格值,使用它们进行数学运算,并将输出写入新工作表。我一直在收到ErrorType。我之前已成功运行代码,但只是添加了它的这方面,因此代码已被提炼到下面:

import openpyxl

#set up ws from file, and ws_out write to new file

def get_data():
    first = 0
    second = 0
    for x in range (1, 1000):
        if ws.cell(row=x, column=1).value == 'string':
            for y in range (1, 10):            #Only need next ten rows after 'string'

                ws_out.cell(row=y, column=1).value = ws.cell(row=x+y, column=1).value

                second = first                             #displaces first -> second
                first = ws.cell(row=x+y, column=1).value/100     #new value for first
                difference = first - second

                ws_out.cell(row=x+y+1, column=1).value = difference    #add to output
            break

引发TypeError消息:

  

first = ws.cell(row = x + y,column = 1).value)/ 100
  TypeError:/:'NoneType'和'int'

的不支持的操作数类型

我认为这分别是指ws.cell值和100,所以我也尝试过:

first = int(ws.cell(row=x, column=1))/100 #also tried with float

提出了什么:

  

TypeError:int()参数必须是字符串或数字

我已经确认列中的每个单元格仅由数字组成。另外,openpyxl的cell.data_type返回'n'(据我所知,文档可能是数字)。

我还测试了更简单的数学,并且有相同的错误。

我所有的搜索似乎都指向openpyxl通常表现得像这样。我做错了什么,或者这仅仅是模块的限制?如果是这样,是否有任何程序化的解决方法?

作为奖励,我会非常感谢您更简洁地编写代码的建议。我刚刚开始,并且觉得必须有更清晰的方式来写这样的想法。

Python 3.3,openpyxl-1.6.2,Windows 7


摘要

cfi的回答帮助我解决了问题,尽管我使用了稍微不同的解决方法。在检查原始文件时,有一个空单元格(我之前错过了)。由于我将稍后在具有更多偶发空单元格的列上重新使用此代码,因此我使用了:

if ws.cell(row=x+r, column=40).data_type == 'n':
    second = first                             #displaces first -> second
    first = ws.cell(row=x+y, column=1).value/100     #new value for first
    difference = first - second

    ws_out.cell(row=x+y+1, column=1).value = difference    #add to output

因此,如果指定的单元格为空,则会被忽略并跳过。

1 个答案:

答案 0 :(得分:0)

您是否100%确定(已经验证)您正在访问的所有单元格实际上都有值? (编辑:执行print("dbg> cell value of {}, {} is {}".format(row, 1, ws.cell(row=row, column=1).value))验证内容)

我建议使用openpyxl内省方法迭代现有行,而不是通过固定范围(1,1000)。 E.g:

wb=load_workbook(inputfile)
    for ws in wb.worksheets:
        for row in ws.rows:
            for cell in row:  value = cell.value

获取值时,请不要忘记提取.value属性:

first = ws.cell(row=x+y, column=1).value/100    #new value for first

作为一般说明:xy是2D坐标的有用变量名称。不要将它们用于行。它会误导其他必须阅读代码的人。您可以使用xstart_row或类似内容来代替row_offset。您可以使用y代替row,而可以让它从第一个索引start_row+1开始。

一些示例代码(未经测试):

def get_data():
    first = 0
    second = 0
    for start_row in range (1, ws.rows):
        if ws.cell(row=start_row, column=1).value == 'string':
            for row in range (start_row+1, start_row+10):

                ws_out.cell(row=start_row, column=1).value = ws.cell(row=row, column=1)

                second = first
                first = ws.cell(row=row, column=1).value/100
                difference = first - second

                ws_out.cell(row=row+1, column=1).value = difference
            break

现在有了这段代码,我仍然不明白你想要实现的目标。 break缩进是否正确?如果是,则第一次匹配string时,外部循环将由break退出。那么,变量firstsecond

的重点是什么

修改:同时确保您的阅读写入cell().value而不只是cell()