comparison excel.py @ 73:4bd5de7ac247

added Range, M and RC
author Henry S. Thompson <ht@markup.co.uk>
date Mon, 03 Jul 2017 16:25:49 +0100
parents 54bb53434887
children 7827e686be75
comparison
equal deleted inserted replaced
72:0654e37583b5 73:4bd5de7ac247
2 '''Class model for analysis of Excel spreadsheets''' 2 '''Class model for analysis of Excel spreadsheets'''
3 from jsonweb.encode import to_object, dumper 3 from jsonweb.encode import to_object, dumper
4 from jsonweb.decode import from_object, loader 4 from jsonweb.decode import from_object, loader
5 import json 5 import json
6 import eDecoder 6 import eDecoder
7
8 import re
7 9
8 try: 10 try:
9 string_types=basestring 11 string_types=basestring
10 except NameError: 12 except NameError:
11 string_types=str 13 string_types=str
56 def __init__(self,name,parent=None,ranges=[],content=[]): 58 def __init__(self,name,parent=None,ranges=[],content=[]):
57 if parent is not None: 59 if parent is not None:
58 assert(isinstance(parent,(Region,Sheet))) 60 assert(isinstance(parent,(Region,Sheet)))
59 self.parent=parent 61 self.parent=parent
60 ranges=list(ranges) 62 ranges=list(ranges)
61 assert(all(isinstance(s,Range) for s in ranges)) 63 assert(all(isinstance(s,string_types) for s in ranges))
62 self.ranges=ranges 64 self.ranges=[Range(s) for s in ranges]
63 content=list(content) 65 content=list(content)
64 assert(all(isinstance(s,(Region,string_types)) for s in content)) 66 assert(all(isinstance(s,(Region,string_types)) for s in content))
65 self.content=content 67 self.content=content
66 assert(isinstance(name,string_types)) 68 assert(isinstance(name,string_types))
67 self.name=name 69 self.name=name
68 if parent is not None: 70 if parent is not None:
69 parent.addRegion(self) 71 parent.addRegion(self)
70 72
71 def addRegion(self,content): 73 def addRegion(self,content):
72 assert(isinstance(content,(Region,string_types))) 74 assert(isinstance(content,(Region,string_types)))
75 # convert
73 self.content.append(content) 76 self.content.append(content)
77
78 cell=r'(\$?)([A-Z]+)(\$?)([1-9][0-9]*)'
79 RANGE=re.compile(cell+(r'(:%s)?'%cell))
80 C=0 # Column
81 R=1 # Row
82 F=0 # Fixed ($)
83 V=1 # Value
84 @to_object()
85 class Range(object):
86 def __init__(self,estr):
87 m=RANGE.match(estr)
88 if m is None:
89 raise ValueError("string %s doesn't represent a range"%estr)
90 rgrps=m.groups()
91 self.tl=((rgrps[0]=='$',rgrps[1]),((rgrps[2]=='$',int(rgrps[3]))))
92 if rgrps[4] is None:
93 self.br=None
94 self.dim=0
95 self.vertical=None
96 else:
97 self.br=((rgrps[5]=='$',rgrps[6]),((rgrps[7]=='$',int(rgrps[8]))))
98 if self.tl[C][V]==self.br[C][V]:
99 self.dim=1
100 self.vertical=True
101 elif self.tl[R][V]==self.br[R][V]:
102 self.dim=1
103 self.vertical=False
104 else:
105 self.dim=2
106 self.vertical=None
107
108 def __str__(self):
109 tls=_cellStr(self.tl[C])+_cellStr(self.tl[R])
110 if self.br is None:
111 return tls
112 else:
113 return '%s:%s'%(tls,_cellStr(self.br[C])+_cellStr(self.br[R]))
114
115 def _cellStr(dvp):
116 (dollar,val)=dvp
117 return '%s%s'%('$' if dollar else '',str(val))
118
119 @from_object()
120 @to_object(exclude_nulls=True)
121 class M(Region):
122 def __init__(self,name,sheet=None,ranges=[],labels=[],data=[]):
123 super(M,self).__init__(name,sheet,ranges,labels,data)
124
125 @from_object()
126 @to_object(exclude_nulls=True)
127 class RC(Region):
128 def __init__(self,name,sheet=None,ranges=[],labels=[],data=[]):
129 super(RC,self).__init__(name,sheet,ranges,labels,data)
74 130
75 @from_object() 131 @from_object()
76 @to_object(exclude_nulls=True,suppress=["sheet"]) 132 @to_object(exclude_nulls=True,suppress=["sheet"])
77 class Table(Region): 133 class Table(M):
78 def __init__(self,name,sheet=None,ranges=[],labels=[],data=[]): 134 def __init__(self,name,shape='mixed',sheet=None,ranges=[],labels=[],data=[]):
79 super(Table,self).__init__(name,sheet,ranges) 135 super(Table,self).__init__(name,sheet,ranges)
136 assert(shape in ('columns','rows','mixed'))
137 self.shape=shape # if columns or rows, that's what correspond to DB columns
80 labels=list(labels) 138 labels=list(labels)
81 assert(all(isinstance(s,Label) for s in labels)) 139 assert(all(isinstance(s,Label) for s in labels))
82 self.labels=labels 140 self.labels=labels
83 data=list(data) 141 data=list(data)
84 assert(all(isinstance(s,Region) for s in data)) 142 assert(all(isinstance(s,Region) for s in data))
103 else: 161 else:
104 self.addData(region) 162 self.addData(region)
105 163
106 def lt(filename): 164 def lt(filename):
107 with open(filename,'r') as js: 165 with open(filename,'r') as js:
108 return json.loads(js.read(),cls=eDecoder.eDecoder) 166 return loader(js.read(),cls=eDecoder.eDecoder)