2013-07-08 139 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