A very quick look on the openpyxl
docs and you might find this page saying
openpyxl never evaluates formula
Before going any further, it should be noted that the possible duplicate links have answers pertaining to other modules, and these are usually the accepted answers. With those modules you don't have to implement your own parsing. Which can be anywhere from challenging to near impossible for more complex systems.
If you're doing pretty simple stuff, it's not terribly difficult with the Tokenizer
class. Usage:
>>> from openpyxl.formula import Tokenizer
>>> tok = Tokenizer("""=IF($A$1,"then True",MAX(DEFAULT_VAL,'Sheet 2'!B1))""")
>>> print("\n".join("%12s%11s%9s" % (t.value, t.type, t.subtype) for t in tok.items))
IF( FUNC OPEN
$A$1 OPERAND RANGE
, SEP ARG
"then True" OPERAND TEXT
, SEP ARG
MAX( FUNC OPEN
DEFAULT_VAL OPERAND RANGE
, SEP ARG
'Sheet 2'!B1 OPERAND RANGE
) FUNC CLOSE
) FUNC CLOSE
Pay special attention, everything is a string, so evaluating formulas is best done with eval()
So if you edited your code a bit (new/changed lines marked with #
),
import openpyxl
from openpyxl import Workbook
from openpyxl.formula import Tokenizer #
wb = openpyxl.load_workbook('test.xlsx')
sheet1 = wb['Sheet1']
C1Formula = sheet1['C1'].value #
C1Token = Tokenizer(C1Formula) #
C1Value = handle_token(sheet1, C1Token) #
print('C1: ', C1Value)
Where handle_token()
is up to you for how complicated you wanted it. A couple simple and perhaps hack-y examples for C1: =A1 + B1
and other binary operators: (these don't work for ^
as python uses that for bitwise XOR)
def handle_token(sheet, token):
formula = ""
for t in token.items:
if t.type is 'OPERAND':
formula += str(sheet[t.value])
else:
formula += str(t.value)
return eval(formula)
Or if you prefer (this can be converted to a one-liner, not recommended) using a generator:
def handle_token(sheet, token):
parsed = str(sheet[t.value].value) if t.type is 'OPERAND' else t.value for t in token.items
formula = "".join(parsed)
return eval(formula)