Значение именованного диапазона Python xlrd

Использование XLRD в Python для чтения из Excel.

Простой сценарий. У меня есть ячейка со значением, и это связано с именованным диапазоном.

NamedRange "Foo" = Sheet1!$A$1 Значение в A1 равно "Bar"

book =xlrd.open_workbook("")

rng =  book.name_map['foo'][0]  # lower case for some reason.

print rng.???   # how to print the cell value bar??

Я просто хочу сослаться на именованный диапазон «Foo» в коде Python и распечатать значение «Bar» ячейки.

РЕДАКТИРОВАТЬ: вот еще один более полный пример:

import xlrd

workbook = xlrd.open_workbook('/path/to/metester.xls')
cell_obj = workbook.name_and_scope_map.get(('sales', -1))
# this does print Sheet1!$A$1
print cell_obj.formula_text
# this raises the NoneTypeError
print cell_obj.cell()

Formula_text нужен для того, чтобы Excel мог прочитать файл. В моем случае именованная ячейка — это «продажи» на Листе 1, ячейка A1.

Возвращает:

Sheet1!$A$1
Traceback (most recent call last):
  File "tester.py", line 7, in <module>
    print cell_obj.cell()
  File "/usr/local/lib/python2.7/dist-packages/xlrd/book.py", line 253, in cell
    self.dump(self.book.logfile,
AttributeError: 'NoneType' object has no attribute 'logfile'

person Dickster    schedule 26.06.2014    source источник
comment
любое решение этого? Я пробовал rng.cell(), и это дает мне ошибку: AttributeError: объект «NoneType» не имеет атрибута «файл журнала». Я использую версию 0.9.3   -  person user_78361084    schedule 26.01.2015
comment
@llamawithabowlcut Хм, эта ошибка атрибута не соответствует 'исходный код' - Name.cell() работает только с XLRDError. Вы уверены, что именно эта строка выдает вам ошибку? поскольку это относится к logfile - может быть, это ваша настройка ведения журнала или что-то, что на самом деле не работает? Не могли бы вы дать нам немного более полный вариант использования? Может быть, ваш вопрос не совпадает с исходным вопросом от @Dickster, и вам нужен новый вопрос?   -  person J Richard Snape    schedule 26.01.2015
comment
@JRichardSnape: Пожалуйста, смотрите мои правки. У меня нет другого импорта, и это полный и полный код.   -  person user_78361084    schedule 27.01.2015
comment
@llamawithabowlcut Смотрите мой ответ - ваш вопрос отличается от исходного. Буду признателен, если вы подтвердите, что используете .xlsx, а не .xls. Дайте мне знать, если это сработает - потребовалось время, чтобы понять.   -  person J Richard Snape    schedule 27.01.2015


Ответы (2)


Во-первых, это нижний регистр, как описано в информации о модуле xlrd (https://secure.simplistix.co.uk/svn/xlrd/trunk/xlrd/doc/xlrd.html?p=4966):

имя_карта [#]

Сопоставление из lower_case_name в список объектов Name. Список отсортирован в порядке охвата. Обычно в списке будет один элемент (глобального масштаба).

У вас есть два варианта. Если вы действительно устанавливаете имя только для одной ячейки, вы используете метод «ячейка» класса Name (см. документы):

import xlrd
book = xlrd.open_workbook("")
Name = book.name_map['foo'][0]
print(Name.cell())

Приставка:

text:'Bar'

Однако если вы назвали весь диапазон значений, вам нужно использовать метод area2d класса Name:

import xlrd
book = xlrd.open_workbook("q1.xls")
Name = book.name_map['foo'][0]
Sheet, rowxlo, rowxhi, colxlo, colxhi = Name.area2d()
for i in range(rowxhi):
    print(Sheet.cell(i,0))

Приставка:

text:'Bar'
person jonnybazookatone    schedule 26.01.2015
comment
Как я уже упоминал выше, ячейка () дает мне ошибку: AttributeError: объект «NoneType» не имеет атрибута «файл журнала» (Sheet.cell (i, 0)) также дает мне ту же ошибку) - person user_78361084; 26.01.2015
comment
Вам нужно предоставить более подробную информацию, пример кода, как отметил @J Richard Snape - person jonnybazookatone; 26.01.2015
comment
Спасибо за объяснение, Джонни. Я пытаюсь использовать диапазон имен для таблицы в Excel, но не могу найти соответствующую функцию из xlrd. Вы случайно не знаете, как читать таблицу с присвоенным диапазоном имен? - person Zong; 04.01.2017
comment
@Zong Я бы посоветовал вам открыть новый вопрос и дать ссылку на него здесь, на него ответят гораздо быстрее, чем если бы вы ждали меня. - person jonnybazookatone; 05.01.2017

На первоначальный вопрос и пример точно отвечает @jonnybazookatone answer ниже. Расширенный пример — это другая ошибка. Мне кажется, что это недостаток xlrd, но я взломал решение для того, что вы хотите. Первый раздел — объяснение, последний раздел — хак.

Объяснение

Глядя на более развернутый пример, сообщение об ошибке создается из строк кода, которые обрабатывают состояние ошибки для объекта Name, где по какой-то причине не удалось получить результат вычисления формул в диапазоне Name.

Фактическая зарегистрированная ошибка

AttributeError: 'NoneType' object has no attribute 'logfile'

является вторичной ошибкой, указывающей, что self.book оценивается как None для этого объекта Name.

Во-вторых, вы упускаете важную деталь, я думаю, что ваш файл Excel имеет формат .xlsx. Обратите внимание на завершающий x. В обычном синтаксическом анализаторе xls объект Name не имеет атрибута formula_text, поэтому ваш код завершается со следующей ошибкой.

Traceback (most recent call last):
  File "D:\q1.py", line 16, in <module>
    print cell_obj.formula_text
AttributeError: 'Name' object has no attribute 'formula_text'

Пожалуйста, будьте осторожны с вашими примерами кода - мне потребовалось некоторое время, чтобы отследить эту разницу - файлы xlsx анализируются совершенно другим кодом в xlrd. С исправленным xlsx я могу воспроизвести вашу ошибку.

Атрибут formula_text в этом случае просто дает ссылку в нотации RC на ячейку, которая является вашим именованным диапазоном. Следует отметить, что функция устанавливающая formula_text имеет оговорку "#### UNDER CONSTRUCTION ####" и существует с момента первоначальной фиксации модуля xlsx в 2012 году.

Проблема в том, насколько я вижу, формулы никогда не оцениваются при открытии xlsx, поэтому вы сталкиваетесь с ошибкой, что Name.res равно None, и поэтому вы видите свою ошибку. Кажется, это xlrd ошибка/фича.

взломать

Я придумал неприятный хак, который будет делать то, что вы хотите в случае, когда ваш диапазон представляет собой одну ячейку, путем расширения ссылки на ячейку. Обратите внимание, что он не будет работать для именованных диапазонов, ссылающихся на более чем одну ячейку, как сейчас, но его можно легко изменить, чтобы справиться с этим сценарием:

hack = cell_obj.formula_text
(sheetName,ref) = hack.split('!')
(discard,colStr,rowStr) = ref.split('$')
col = 0
for i in range(len(colStr)):
    colAdd = string.ascii_uppercase.index(colStr)
    col += colAdd * 10**i
row = int(rowStr)-1
print("Trying to evaluate cell",row,col,"in sheet",sheetName)
print workbook.sheet_by_name(sheetName).cell(row,col)
person J Richard Snape    schedule 27.01.2015