【问题标题】:Get formula from Excel cell with python xlrd使用 python xlrd 从 Excel 单元格中获取公式
【发布时间】:2011-06-09 02:12:45
【问题描述】:

我必须将算法从 Excel 工作表移植到 Python 代码,但我必须从 Excel 文件对算法进行逆向工程

Excel 工作表相当复杂,它包含许多单元格,其中有引用其他单元格的公式(也可以包含公式或常数)。

我的想法是用python脚本来分析表格,建立一个单元格之间的依赖关系表,即:

A1 取决于 B4,C5,E7 公式:“=sqrt(B4)+C5*E7”
A2 取决于 B5,C6 公式:“=sin(B5)*C6”
...

xlrd python 模块允许读取 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 对象中获取公式。 在documentation 中,他们说可以获得公式的字符串版本(英文是因为没有关于存储在 Excel 文件中的函数名称翻译的信息)。他们谈论 NameOperand 类中的公式(表达式),无论如何我无法理解如何通过 Cell 获取这些类的实例必须包含它们的类实例。

您能推荐一个从单元格中获取公式文本的代码 sn-p 吗?

【问题讨论】:

    标签: python excel formula xls xlrd


    【解决方案1】:

    [Dis]声明:我是xlrd 的作者/维护者。

    公式文本的文档引用是关于“名称”公式的;阅读文档开头附近的“命名引用、常量、公式和宏”部分。这些公式在工作表范围或书籍范围内与名称相关联;它们与单个细胞无关。示例:PI 映射到 =22/7SALES 映射到 =Mktng!$A$2:$Z$99。编写名称公式反编译器是为了支持检查已定义名称的更简单和/或常见用法。

    公式一般有几种:单元格、共享和数组(都与单元格直接或间接关联)、名称、数据验证和条件格式。

    将一般公式从字节码反编译为文本是一项“正在进行中的工作”,进展缓慢。请注意,假设它可用,您将需要解析文本公式以提取单元格引用。正确解析 Excel 公式并非易事;与 HTML 一样,使用正则表达式看起来很容易,但不起作用。最好直接从公式字节码中提取引用。

    还要注意,基于单元格的公式可以引用名称,而名称公式既可以引用单元格,也可以引用其他名称。因此,有必要从基于单元格的公式和名称公式中提取单元格和名称引用。获取有关可用共享公式的信息可能对您有用;否则解析以下内容:

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

    您需要自己推断B3:B60 公式之间的相似性。

    无论如何,上述任何一项都不太可能很快推出——xlrd 优先级在别处。

    【讨论】:

    • 有没有使用xlrd模块的Name Class的例子?
    【解决方案2】:

    更新:我已经实现了一个小库来完成您所描述的操作:从 Excel 电子表格中提取单元格和依赖项并将它们转换为 python 代码。代码is on github,欢迎打补丁:)


    只是补充一点,您始终可以使用win32com 与 excel 进行交互(速度不是很快,但可以)。这确实允许您获得公式。一个tutorial can be found here[cached copy]和详细信息可以找到in this chapter[cached copy]

    基本上你只是这样做:

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

    至于构建单元格依赖关系表,一个棘手的事情是解析 excel 表达式。如果我没记错的话,您提到的 Trace 代码并不总是正确执行此操作。我见过的最好的是the algorithm by E. W. Bachtal,其中有一个python实现,效果很好。

    【讨论】:

      【解决方案3】:

      所以我知道这是一篇非常古老的帖子,但我找到了一种从工作簿中的所有工作表中获取公式以及让新创建的工作簿保留所有格式的好方法。

      第一步是将 .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),"")',
      

      【讨论】:

        【解决方案4】:

        现在似乎不可能用 xlrd 做你想做的事。您可以查看this post,详细说明实现所需功能为何如此困难。

        请注意,开发团队在 python-excel google 小组的支持方面做得很好。

        【讨论】:

        • 当然,Excel 解析器的可用性是一个很好的东西,但我真的希望得到甚至公式参考信息。无论如何,我找到了一个用 VB 宏编写的依赖跟踪器,它使用 christopherteh.com/trace 上的 graphwiz 创建了一个依赖图。最好有一个依赖表,以便在 python 中更快地分析和移植算法。
        【解决方案5】:

        是的! 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
        

        【讨论】:

        • 是的,但它不在主题范围内。这里你没有使用 xldr,你使用的是原生 Excel COM(所以你需要安装 MS Office)
        【解决方案6】:

        我知道这篇文章有点晚了,但这里没有提到一个建议。从工作表中剪切所有条目并使用特殊粘贴 (OpenOffice) 进行粘贴。这会将公式转换为数字,因此无需额外的编程,这对于小型工作簿来说是一个合理的解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多