Obtenir la formule de la cellule Excel avec python xlrd

j'ai portage d'un algorithme D'une feuille Excel vers le code python mais je dois désosser l'algorithme à partir du fichier Excel.

la feuille Excel est assez compliquée, elle contient beaucoup de cellules dans lesquelles il y a des formules qui se réfèrent à d'autres cellules (qui peuvent aussi contenir une formule ou une constante).

mon idée est d'analyser avec un script python la feuille construisant une sorte de table de dépendances entre les cellules, qui est:

A1 dépend de B4, C5, E7 formule: "=sqrt (B4)+C5*E7"

A2 dépend de B5, C6 formule: "=sin (B5) * C6"

...

xlrd le module python permet de lire un classeur XLS mais pour le moment je peux accéder au valeur d'une cellule, pas l' formule.

Par exemple, avec le code suivant, je peux obtenir tout simplement la valeur d'un cellule:

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)

quoi qu'il en soit, il semble n'avoir aucun moyen d'obtenir le formul de L'objet de la cellule retourné par le .cellule.(..) méthode. documentation ils disent qu'il est possible d'obtenir une version string de la formule (en anglais parce qu'il n'y a aucune information sur la traduction du nom de la fonction stockée dans le fichier Excel). Ils parlent de formules (expressions) dans le Nom et Opérande classes, de toute façon je ne comprends pas comment obtenir les instances de ces classes par le Cellule instance de classe qui doit les contenir.

pourriez-vous suggérer un extrait de code qui obtient le texte de la formule d'une cellule?

20
demandé sur alexroat 2011-01-14 14:12:04

5 réponses

[Dis]déclarant: je suis l'auteur ou le responsable de l' xlrd.

la documentation les références au texte de formule concernent les formules" name"; lisez la section "Named references, constants, formules, and macros" près du début des docs. Ces formules sont associées à l'échelle de la feuille ou du livre à un nom; elles ne sont pas associées à des cellules individuelles. Exemples: PI cartes =22/7,SALES cartes =Mktng!$A:$Z. Le nom-formule decompiler a été écrit pour soutenir l'inspection de la utilisation plus simple et / ou courante de noms définis.

les formules en général sont de plusieurs types: cellule, partagée, et tableau (tous associés à une cellule, directement ou indirectement), nom, validation des données, et formatage conditionnel.

la décomposition des formules générales du bytecode au texte est un "travail en cours", lentement. Notez que s'il était disponible, vous devrez alors analyser la formule du texte pour extraire les références de la cellule. Parsing Excel Formules correctement est ce N'est pas une tâche facile; comme avec HTML, utiliser regexes semble facile mais ne fonctionne pas. Il serait préférable d'extraire les références directement à partir de la formule de bytecode.

notez aussi que les formules basées sur les cellules peuvent renvoyer à des noms, et les formules de noms peuvent renvoyer à des cellules et à d'autres noms. Il serait donc nécessaire d'extraire à la fois les références de cellules et de noms à partir de formules basées sur les cellules et les noms. Il peut être utile pour vous d'avoir des informations sur les formules partagées disponibles; autrement avoir analysé le suivantes:

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

vous devez déduire la similitude entre les B3:B60 formules vous-même.

En tout cas, aucun des ci-dessus est susceptible d'être disponible à tout moment bientôt -- xlrd les priorités sont ailleurs.

19
répondu John Machin 2011-01-14 20:16:46

mise à Jour: j'ai mis en place une petite bibliothèque pour faire exactement ce que vous décrivez: extraire les cellules et les dépendances d'une feuille de calcul Excel et les convertir en code python. Code est sur github, les correctifs de bienvenue :)


juste pour ajouter que vous pouvez toujours interagir avec excel en utilisant win32com (pas très rapide mais ça marche). Cela ne vous permettent d'obtenir la formule. tutoriel peut être trouvé ici et les détails peuvent être trouvés ce chapitre[copie mise en cache].

essentiellement vous faites juste:

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

quant à la construction d'une table de dépendances de cellules, une chose délicate est l'analyse des expressions excel. Si je me souviens bien, le code de Trace que vous avez mentionné ne le fait pas toujours correctement. Le meilleur que j'ai vu, c'est l'algorithme par E. W. Bachtal, dont une implémentation python est disponible qui fonctionne bien.

11
répondu dgorissen 2017-05-08 05:44:53

donc je sais que c'est un très vieux post, mais j'ai trouvé un moyen décent d'obtenir les formules de toutes les feuilles dans un classeur aussi bien que d'avoir le classeur nouvellement créé conservent tout le formatage.

la Première étape est d'enregistrer une copie de votre .xlsx fichier .xls -- Utiliser le .xls comme nom de fichier dans le code ci-dessous

Utilisant 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

Structure du dictionnaire 'sheet_formulas'

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

Exemple:

{u'CY16': {'A1': '=Data!B5',
  'B1': '=Data!B1',
  'B10': '=IFERROR(Data!B12,"")',
  'B11': '=IFERROR(SUM(B9:B10),"")',
3
répondu mkultra 2016-11-13 18:05:38

Il semble qu'il est impossible maintenant de faire ce que vous voulez avec xlrd. Vous pouvez avoir un coup d'oeil à ce post pour la description détaillée de la raison pour laquelle il est si difficile de mettre en œuvre la fonctionnalité dont vous avez besoin.

notez que l'équipe de développement fait un excellent travail pour le support du groupe google de python-excel.

1
répondu Steve 2011-01-14 13:47:00

je sais que ce post est un peu en retard mais il y a une suggestion qui n'a pas été abordé ici. Découper toutes les entrées de la feuille de travail et Coller en utilisant la pâte spéciale (OpenOffice). Cela convertira les formules en nombres de sorte qu'il n'y a pas besoin de programmation supplémentaire et c'est une solution raisonnable pour les petits cahiers.

0
répondu Erik 2013-07-27 13:10:14