Module tkintertable.TableFormula
Module implements the Formula class for cell formulae. Created Oct 2008 Copyright (C) Damien Farrell
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Source code
#!/usr/bin/env python
"""
Module implements the Formula class for cell formulae.
Created Oct 2008
Copyright (C) Damien Farrell
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
#import sys, os
from __future__ import absolute_import, division, print_function
try:
from tkinter import *
from tkinter.ttk import *
from tkinter import filedialog, messagebox, simpledialog
except:
from Tkinter import *
from ttk import *
import tkFileDialog as filedialog
import tkSimpleDialog as simpledialog
import tkMessageBox as messagebox
from types import *
import re
class Formula(object):
"""A class to handle formulas functionality in the table"""
#replace symbols in recnames with strings for proper parsing
#replace = {'+':'plus', '-':'minus', '*':'mult',
def __init__(self):
return
@classmethod
def isFormula(cls, rec):
"""Evaluate the cell and return true if its a formula"""
isform = False
if type(rec) is dict:
if 'formula' in rec:
isform = True
return isform
@classmethod
def getFormula(cls, rec):
"""Get the formula field string"""
if not type(rec) is dict:
return None
string = rec['formula']
#print string
return string
@classmethod
def readExpression(cls, expr):
"""Get the operands and operators into lists from a string expression"""
ops = []
vals = []
p = re.compile('[()*/+-]')
x = p.split(expr)
ops = p.findall(expr)
#print expr, ops
for i in x:
if i == '':
vals.append(i)
else:
vals.append(eval(i))
#print ops, vals
return vals, ops
@classmethod
def doExpression(cls, vals, ops, getvalues=True):
"""Create an expression string from provided operands and operators"""
expr = ''
if getvalues == True:
for i in range(len(vals)):
if vals[i] != '':
vals[i] = float(vals[i])
if len(ops)>len(vals):
while len(ops):
#use lists as queues
expr += ops.pop(0)
if len(vals)!=0:
v=vals.pop(0)
if v == '':
pass
else:
expr += str(v)
elif len(ops)<len(vals):
while len(vals):
#use lists as queues
v=vals.pop(0)
if v == '':
pass
else:
expr += str(v)
if len(ops)!=0:
expr += ops.pop(0)
return expr
@classmethod
def doFormula(cls, cellformula, data):
"""Evaluate the formula for a cell and return the result
takes a formula dict or just the string as input"""
if type(cellformula) is dict:
cellformula = cellformula['formula']
vals = []
cells, ops = cls.readExpression(cellformula)
#get cell records into their values
for i in cells:
if type(i) is ListType:
recname, col= i
if data.has_key(recname):
if data[recname].has_key(col):
v = data[recname][col]
if cls.isFormula(v):
#recursive
v = cls.doFormula(cls.getFormula(v),data)
vals.append(v)
else:
return ''
else:
return ''
elif i== '' or type(i) is IntType or type(i) is FloatType:
vals.append(i)
else:
return ''
if vals == '':
return ''
#print vals, ops
expr = cls.doExpression(vals, ops)
#print 'expr', expr
result = eval(expr)
return str(round(result,3))
Classes
class Formula
-
A class to handle formulas functionality in the table
Source code
class Formula(object): """A class to handle formulas functionality in the table""" #replace symbols in recnames with strings for proper parsing #replace = {'+':'plus', '-':'minus', '*':'mult', def __init__(self): return @classmethod def isFormula(cls, rec): """Evaluate the cell and return true if its a formula""" isform = False if type(rec) is dict: if 'formula' in rec: isform = True return isform @classmethod def getFormula(cls, rec): """Get the formula field string""" if not type(rec) is dict: return None string = rec['formula'] #print string return string @classmethod def readExpression(cls, expr): """Get the operands and operators into lists from a string expression""" ops = [] vals = [] p = re.compile('[()*/+-]') x = p.split(expr) ops = p.findall(expr) #print expr, ops for i in x: if i == '': vals.append(i) else: vals.append(eval(i)) #print ops, vals return vals, ops @classmethod def doExpression(cls, vals, ops, getvalues=True): """Create an expression string from provided operands and operators""" expr = '' if getvalues == True: for i in range(len(vals)): if vals[i] != '': vals[i] = float(vals[i]) if len(ops)>len(vals): while len(ops): #use lists as queues expr += ops.pop(0) if len(vals)!=0: v=vals.pop(0) if v == '': pass else: expr += str(v) elif len(ops)<len(vals): while len(vals): #use lists as queues v=vals.pop(0) if v == '': pass else: expr += str(v) if len(ops)!=0: expr += ops.pop(0) return expr @classmethod def doFormula(cls, cellformula, data): """Evaluate the formula for a cell and return the result takes a formula dict or just the string as input""" if type(cellformula) is dict: cellformula = cellformula['formula'] vals = [] cells, ops = cls.readExpression(cellformula) #get cell records into their values for i in cells: if type(i) is ListType: recname, col= i if data.has_key(recname): if data[recname].has_key(col): v = data[recname][col] if cls.isFormula(v): #recursive v = cls.doFormula(cls.getFormula(v),data) vals.append(v) else: return '' else: return '' elif i== '' or type(i) is IntType or type(i) is FloatType: vals.append(i) else: return '' if vals == '': return '' #print vals, ops expr = cls.doExpression(vals, ops) #print 'expr', expr result = eval(expr) return str(round(result,3))
Static methods
def doExpression(vals, ops, getvalues=True)
-
Create an expression string from provided operands and operators
Source code
@classmethod def doExpression(cls, vals, ops, getvalues=True): """Create an expression string from provided operands and operators""" expr = '' if getvalues == True: for i in range(len(vals)): if vals[i] != '': vals[i] = float(vals[i]) if len(ops)>len(vals): while len(ops): #use lists as queues expr += ops.pop(0) if len(vals)!=0: v=vals.pop(0) if v == '': pass else: expr += str(v) elif len(ops)<len(vals): while len(vals): #use lists as queues v=vals.pop(0) if v == '': pass else: expr += str(v) if len(ops)!=0: expr += ops.pop(0) return expr
def doFormula(cellformula, data)
-
Evaluate the formula for a cell and return the result takes a formula dict or just the string as input
Source code
@classmethod def doFormula(cls, cellformula, data): """Evaluate the formula for a cell and return the result takes a formula dict or just the string as input""" if type(cellformula) is dict: cellformula = cellformula['formula'] vals = [] cells, ops = cls.readExpression(cellformula) #get cell records into their values for i in cells: if type(i) is ListType: recname, col= i if data.has_key(recname): if data[recname].has_key(col): v = data[recname][col] if cls.isFormula(v): #recursive v = cls.doFormula(cls.getFormula(v),data) vals.append(v) else: return '' else: return '' elif i== '' or type(i) is IntType or type(i) is FloatType: vals.append(i) else: return '' if vals == '': return '' #print vals, ops expr = cls.doExpression(vals, ops) #print 'expr', expr result = eval(expr) return str(round(result,3))
def getFormula(rec)
-
Get the formula field string
Source code
@classmethod def getFormula(cls, rec): """Get the formula field string""" if not type(rec) is dict: return None string = rec['formula'] #print string return string
def isFormula(rec)
-
Evaluate the cell and return true if its a formula
Source code
@classmethod def isFormula(cls, rec): """Evaluate the cell and return true if its a formula""" isform = False if type(rec) is dict: if 'formula' in rec: isform = True return isform
def readExpression(expr)
-
Get the operands and operators into lists from a string expression
Source code
@classmethod def readExpression(cls, expr): """Get the operands and operators into lists from a string expression""" ops = [] vals = [] p = re.compile('[()*/+-]') x = p.split(expr) ops = p.findall(expr) #print expr, ops for i in x: if i == '': vals.append(i) else: vals.append(eval(i)) #print ops, vals return vals, ops