ale*_*oat 24 python excel xls xlrd formula
我必须将算法从Excel工作表移植到python代码,但我必须从Excel文件中对算法进行反向工程.
Excel工作表非常复杂,它包含许多单元格,其中有公式引用其他单元格(也可以包含公式或常量).
我的想法是用python脚本分析构建一个单元格之间依赖关系的表格,即:
A1取决于B4,C5,E7公式:"= sqrt(B4)+ C5*E7"
A2取决于B5,C6公式:"= sin(B5)*C6"
......
所述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)
Run Code Online (Sandbox Code Playgroud)
无论如何,似乎没有办法从.cell(...)方法返回的Cell对象中获取formul .在文档中,他们说可以获得公式的字符串版本(英文版,因为没有关于存储在Excel文件中的函数名转换的信息).他们在Name和Operand类中谈论公式(表达式),无论如何我无法理解如何通过必须包含它们的Cell类实例来获取这些类的实例.
你能建议一个从单元格中获取公式文本的代码片段吗?
Joh*_*hin 21
[Dis] claimer:我是作者/维护者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
Run Code Online (Sandbox Code Playgroud)
你需要自己推断出B3:B60公式之间的相似性.
无论如何,上述任何一种情况都不可能很快就会出现 - xlrd优先事项在其他地方.
dgo*_*sen 12
更新:我已经去了并实现了一个小库来完成您所描述的内容:从Excel电子表格中提取单元格和依赖项并将它们转换为python代码.代码在github上,欢迎补丁:)
只是补充一点,你总是可以使用win32com与excel进行交互(不是很快,但它可以工作).这确实可以让你得到公式.一个教程可以在这里找到和细节可以发现在这一章当中 [缓存副本].
基本上你只是这样做:
app.ActiveWorkbook.ActiveSheet.Cells(r,c).Formula
Run Code Online (Sandbox Code Playgroud)
至于构建单元依赖关系表,一个棘手的问题是解析excel表达式.如果我没记错的话,你提到的跟踪代码并不总能正确地做到这一点.我见过的最好的是EW Bachtal的算法,其中有一个python实现可用,效果很好.
因此,我知道这是一篇非常古老的文章,但是我找到了一种不错的方法,可以从工作簿的所有工作表中获取公式,并使新创建的工作簿保留所有格式。
第一步是将.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
Run Code Online (Sandbox Code Playgroud)
字典'sheet_formulas'的结构
{'Worksheet_Name': {'A1_cell_reference':'cell_formula'}}
Run Code Online (Sandbox Code Playgroud)
结果示例:
{u'CY16': {'A1': '=Data!B5',
'B1': '=Data!B1',
'B10': '=IFERROR(Data!B12,"")',
'B11': '=IFERROR(SUM(B9:B10),"")',
Run Code Online (Sandbox Code Playgroud)