Openpyxl: манипуляция значениями ячеек

Вопрос: Я пытаюсь вытащить значения ячейки из листа excel, делать с ними математику и записывать вывод на новый лист. Я продолжаю получать ErrorType. Я успешно запустил код раньше, но просто добавил этот аспект, поэтому код был перегнан ниже: import openpyxl #set up ws from file, and ws_out write to new file def get_data(): first =

Вопрос:

Я пытаюсь вытащить значения ячейки из листа 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 (строка = 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

Таким образом, если указанная ячейка пуста, она игнорируется и пропускается.

Лучший ответ:

Вы на 100% уверены (= подтвердили), что все ячейки, к которым вы обращаетесь, действительно имеют значение? (Изменение: выполнить 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().

Оцените статью
Добавить комментарий