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

Я подтвердил, что каждая ячейка в столбце состоит только из цифр. Кроме того, cell_data_type openpyxl возвращает '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

Действительно ли вы уверены, что все ячейки, к которым вы обращаетесь, действительно имеют значение? (Изменить: Сделайте print("dbg> cell value of {}, {} is {}".format(row, 1, ws.cell(row=row, column=1).value)) для проверки содержимого)

Вместо того, чтобы проходить фиксированный диапазон (1,1000), я бы рекомендовал использовать методы интроспекции openpyxl для итерации по существующим строкам. Например .:

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 

Как общее примечание: x и y полезные имена переменных для 2D координат. Не используйте их для строк. Он вводит в заблуждение других, которые должны прочитать код. Вместо x вы можете использовать start_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. Затем, какова точка переменных first и second?

Редактировать: Также убедитесь, что ваши показания от и, записываются в cell().value не только cell().

+0

«break» отступ правильно, так как я ищу только первый экземпляр 'string' для запуска следующего оператора' if'. 'First' и' Second' смотрят на другие переменные с определенным отношением к 'string' и вычитают один из другого. (В частности, это точки времени: Time 2 вычитается из Time 1 для разницы, при этом Time 1 становится значением Time 2 для следующей строки. Время используется для вычисления скорости для 'string'.) Мне нравится ваша идея переименование некоторых переменных, что я буду делать. Большое спасибо – Jonathan

+0

@Jonathan: Добавлено, что вы можете «print()» значения перед использованием их для вычисления для проверки содержимого. Во-вторых, убедитесь, что вы wrinte в 'cell.value', а не только' cell'. Соответственно отредактировал мой пример кода. - А я просто вижу, что ты уже редактировал свой Q. – cfi

Смежные вопросы