web-dev-qa-db-ja.com

python xlrdを使用してExcelセルから数式を取得します

Excelシートからアルゴリズムをpythonコードに移植する必要がありますが、Excelファイルからアルゴリズムをリバースエンジニアリングする必要があります。

Excelシートは非常に複雑で、他のセルを参照する数式が含まれているセルが多数含まれています(数式または定数を含めることもできます)。

私の考えは、pythonスクリプトを使用して、セル間の依存関係の一種のテーブルを作成するシートを分析することです。

A1はB4、C5、E7の式に依存します: "= sqrt(B4)+ C5 * E7"
A2はB5、C6の式に依存します: "= sin(B5)* C6"
.。

xlrd pythonモジュールはXLSワークブックを読み取ることができますが、現時点では、セルのvalueにアクセスできますが、-ではありません

たとえば、次のコードを使用すると、セルの値を簡単に取得できます。

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ファイルに関数名の翻訳に関する情報が保存されていないため英語で)。彼らはNameクラスとOperandクラスの式(式)について話しますが、とにかくこれらのクラスのインスタンスを取得する方法を理解できませんそれらを含まなければならないCellクラスインスタンスによって。

セルから数式テキストを取得するコードスニペットを提案できますか?

25
alexroat

[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

B3:B60式間の類似性を自分で推測する必要があります。

いずれにせよ、上記のいずれもすぐに利用可能になる可能性はありません-xlrdの優先順位は他の場所にあります。

22
John Machin

Update:Excelスプレッドシートからセルと依存関係を抽出し、それらをpythonコード。コード githubにあります 、パッチは大歓迎です:)


加えて、 win32com を使用していつでもExcelを操作できます(それほど高速ではありませんが、機能します)。これにより、数式を取得できます。 A チュートリアルはここにあります[キャッシュされたコピー] 詳細を確認できます この章では[キャッシュされたコピー]

基本的にあなたはただする:

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

セルの依存関係のテーブルを作成する場合、注意が必要なのはExcelの式を解析することです。私が正しく覚えていれば、あなたが言及したトレースコードは必ずしもこれを正しく行うとは限りません。私が見た中で最高のものは E。W。Bachtalによるアルゴリズム であり、そのうちpython実装が利用可能であり、うまく機能します。

12
dgorissen

非常に古い投稿であることはわかっていますが、ブック内のすべてのシートから数式を取得し、新しく作成したブックにすべての書式を保持させる適切な方法を見つけました。

最初のステップは、.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),"")',
5
mkultra

Xlrdでやりたいことが今は不可能のようです。必要な機能を実装するのが非常に難しい理由の詳細な説明については、 この投稿 をご覧ください。

開発チームは、python-Excelgoogleグループでのサポートに優れた仕事をしていることに注意してください。

2
Steve

あなたがた! 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
0

この投稿が少し遅れていることは知っていますが、ここで取り上げられていない提案が1つあります。ワークシートからすべてのエントリを切り取り、paste special(OpenOffice)を使用して貼り付けます。これにより、数式が数値に変換されるため、追加のプログラミングは必要ありません。これは、小さなワークブックに適したソリューションです。

0
Erik