Получить формулу из ячейки Excel с помощью Python xlrd

Мне нужно перенести алгоритм из таблицы Excel в код Python, но мне нужно реконструировать алгоритм из файла Excel.

Лист Excel довольно сложен, он содержит множество ячеек, в которых есть формулы, которые относятся к другим ячейкам (которые также могут содержать формулу или константу).

Моя идея состоит в том, чтобы проанализировать с помощью скрипта python лист, создающий своего рода таблицу зависимостей между ячейками, то есть:

A1 зависит от формулы B4, C5, E7: "= sqrt (B4) + C5 * E7"
A2 зависит от формулы B5, C6: "= sin (B5) * C6"
...

Модуль python xlrd позволяет читать книгу XLS, но на данный момент я могу получить доступ к значение ячейки, а не формула.

Например, с помощью следующего кода я могу просто получить значение ячейки:

import xlrd

#open the .xls file
xlsname="test.xls"
book = xlrd.open_workbook(xlsname)

#build a dictionary of the names->sheets of the book
sd={}
for s in book.sheets():
    sd[s.name]=s

#obtain Sheet "Foglio 1" from sheet names dictionary
sheet=sd["Foglio 1"]

#print value of the cell J141
print sheet.cell(142,9)

В любом случае, похоже, нет способа получить формулу из объекта Cell, возвращенного методом .cell (...). В документации говорится, что можно получить строковую версию формулы (на английском языке, потому что в файле Excel нет информации о преобразовании имени функции). Они говорят о формулах (выражениях) в классах Name и Operand, в любом случае я не могу понять, как получить экземпляры этих классов с помощью Cell экземпляр класса, который должен их содержать.

Не могли бы вы предложить фрагмент кода, который получает текст формулы из ячейки?


person alexroat    schedule 14.01.2011    source источник


Ответы (6)


[Dis] Заявитель: Я автор / сопровождающий xlrd.

Ссылки в документации на текст формулы относятся к формулам «имени»; прочтите раздел «Именованные ссылки, константы, формулы и макросы» в начале документов. Эти формулы связаны с именем на всем листе или на всей книге; они не связаны с отдельными клетками. Примеры: PI соответствует =22/7, SALES соответствует =Mktng!$A$2:$Z$99. Декомпилятор формулы имени был написан для поддержки проверки более простых и / или часто встречающихся случаев использования определенных имен.

Обычно формулы бывают нескольких видов: ячейка, общий доступ и массив (все прямо или косвенно связаны с ячейкой), имя, проверка данных и условное форматирование.

Декомпиляция общих формул из байт-кода в текст - это медленная «работа». Обратите внимание: если предположить, что он доступен, вам нужно будет проанализировать текстовую формулу, чтобы извлечь ссылки на ячейки. Правильный анализ формул Excel - непростая задача; как и в случае с HTML, использование регулярных выражений выглядит легко, но не работает. Лучше извлекать ссылки прямо из байт-кода формулы.

Также обратите внимание, что формулы на основе ячеек могут относиться к именам, а формулы имен могут относиться как к ячейкам, так и к другим именам. Таким образом, необходимо извлечь ссылки на ячейки и имена как из формул, основанных на ячейках, так и из формул имени. Возможно, вам будет полезно иметь информацию об общих формулах; в противном случае проанализировав следующее:

B2 =A2
B3 =A3+B2
B4 =A4+B3
B5 =A5+B4
...
B60 =A60+B59

вам нужно будет самостоятельно определить сходство B3:B60 формул.

В любом случае ничего из вышеперечисленного вряд ли будет доступно в ближайшее время - xlrd приоритеты лежат в другом месте.

person John Machin    schedule 14.01.2011
comment
Есть какой-нибудь пример использования Name Class модуля xlrd? - person Trimax; 19.03.2014

Обновление: я реализовал небольшую библиотеку, чтобы делать именно то, что вы описываете: извлекать ячейки и зависимости из электронной таблицы Excel и преобразовывать их в код Python. Код находится на github, патчи приветствуются :)


Просто добавлю, что вы всегда можете взаимодействовать с Excel, используя win32com (не очень быстро но работает). Это позволяет получить формулу. учебник можно найти здесь [кешированная копия], а подробности можно найти в этой главе [сохраненная копия].

По сути, вы просто делаете:

app.ActiveWorkbook.ActiveSheet.Cells(r,c).Formula

Что касается построения таблицы зависимостей ячеек, сложная вещь - это синтаксический анализ выражений Excel. Если я правильно помню, код трассировки, который вы упомянули, не всегда делает это правильно. Лучшее, что я видел, это алгоритм Э. В. Бахтала, для которого доступна реализация на Python, которая хорошо работает.

person dgorissen    schedule 29.06.2011

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

Первый шаг - сохранить копию файла .xlsx как .xls - используйте .xls в качестве имени файла в приведенном ниже коде.

Использование Python 2.7

from lxml import etree
from StringIO import StringIO
import xlsxwriter
import subprocess
from xlrd import open_workbook
from xlutils.copy import copy
from xlsxwriter.utility import xl_cell_to_rowcol
import os



file_name = '<YOUR-FILE-HERE>'
dir_path = os.path.dirname(os.path.realpath(file_name))

subprocess.call(["unzip",str(file_name+"x"),"-d","file_xml"])


xml_sheet_names = dict()

with open_workbook(file_name,formatting_info=True) as rb:
    wb = copy(rb)
    workbook_names_list = rb.sheet_names()
    for i,name in enumerate(workbook_names_list):
        xml_sheet_names[name] = "sheet"+str(i+1)

sheet_formulas = dict()
for i, k in enumerate(workbook_names_list):
    xmlFile = os.path.join(dir_path,"file_xml/xl/worksheets/{}.xml".format(xml_sheet_names[k]))
    with open(xmlFile) as f:
        xml = f.read()

    tree = etree.parse(StringIO(xml))
    context = etree.iterparse(StringIO(xml))

    sheet_formulas[k] = dict()
    for _, elem in context:
        if elem.tag.split("}")[1]=='f':
            cell_key = elem.getparent().get(key="r")
            cell_formula = elem.text
            sheet_formulas[k][cell_key] = str("="+cell_formula)

sheet_formulas

Структура словаря sheet_formulas

{'Worksheet_Name': {'A1_cell_reference':'cell_formula'}}

Примеры результатов:

{u'CY16': {'A1': '=Data!B5',
  'B1': '=Data!B1',
  'B10': '=IFERROR(Data!B12,"")',
  'B11': '=IFERROR(SUM(B9:B10),"")',
person mkultra    schedule 13.11.2016

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

Обратите внимание, что команда разработчиков отлично справляется со службой поддержки в группе python-excel google.

person Steve    schedule 14.01.2011
comment
Конечно, наличие синтаксического анализатора Excel - это еще хорошо, но я очень надеюсь получить хотя бы информацию о ссылках на формулы. В любом случае, я нашел трассировщик зависимостей, написанный на макросе VB, который создает граф зависимостей с помощью graphwiz на christopherteh.com/ след. Было бы лучше иметь таблицу зависимостей, которая позволяет быстрее анализировать и переносить алгоритм на python. - person alexroat; 14.01.2011

Вы! С win32com у меня работает.

import    win32com.client
Excel = win32com.client.Dispatch("Excel.Application")

# python -m pip install pywin32
file=r'path Excel file'
wb = Excel.Workbooks.Open(file)
sheet = wb.ActiveSheet

#Get value
val = sheet.Cells(1,1).value
# Get Formula
sheet.Cells(6,2).Formula
person Kairat Koibagarov    schedule 28.11.2019
comment
да, но это не по теме. Здесь вы не используете xldr, вы используете собственный Excel COM (поэтому вам нужно установить MS Office) - person alexroat; 06.12.2019

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

person Erik    schedule 27.07.2013