2013-07-08 95 views
0

我试图从Excel表格中拉出单元格值,与他们进行数学运算,并将输出结果写入新工作表。我不断收到ErrorType。我成功之前已经运行的代码,但只是增加了它的这一方面,因此代码已被蒸馏如下:Openpyxl:操纵单元格值

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: unsupported operand type(s) for /: 'NoneType' and 'int'

我想这是指在ws.cell值和100,分别,所以我也试着:

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

这就提出:

TypeError: int() argument must be a string or a number

我已确认列中的每个单元格都只由数字组成。另外,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 

因此,如果指定单元格是空的,它被忽略和跳过。

+0

请始终发布符合引用错误的代码。 'row = x + r'指代码中不存在的变量'r'。 – cfi

+0

谢谢,更新了错误消息。 – Jonathan

回答

0

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

而不是经过一个固定范围(1,1000)我会推荐使用openpyxl introspection方法遍历现有的行。例如: -

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是有用的变量名的二维坐标。不要将它们同时用于行。它会误导其他必须阅读代码的人。您可以使用start_rowrow_offset或类似的东西来代替x。您可以使用row而不是y,您可以让它从第一个索引即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()

+0

'break'正确缩进,因为我只是寻找'string'的第一个实例来启动下一个'if'语句。 'First'和'Second'查看与'string'特定关系的其他变量,并从另一个中减去一个。 (具体来说,它们是时间点:时间2从时间1减去差值,时间1成为下一行的时间2的值。用于计算字符串速度的时间。)我喜欢你的想法重命名一些变量,我将这样做。非常感谢 – Jonathan

+0

@Jonathan:补充说,在使用它们进行计算以验证内容之前,您可以'print()'值。其次,确保你不是“cell”,而是“cell.value”。相应地编辑我的代码示例。 - 我只是看到你已经编辑过你的Q了.. – cfi