changeset 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 0654e37583b5
children 7827e686be75
files excel.py
diffstat 1 files changed, 63 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/excel.py	Thu Jun 29 17:58:06 2017 +0100
+++ b/excel.py	Mon Jul 03 16:25:49 2017 +0100
@@ -5,6 +5,8 @@
 import json
 import eDecoder
 
+import re
+
 try:
   string_types=basestring
 except NameError:
@@ -58,8 +60,8 @@
       assert(isinstance(parent,(Region,Sheet)))
     self.parent=parent
     ranges=list(ranges)
-    assert(all(isinstance(s,Range) for s in ranges))
-    self.ranges=ranges
+    assert(all(isinstance(s,string_types) for s in ranges))
+    self.ranges=[Range(s) for s in ranges]
     content=list(content)
     assert(all(isinstance(s,(Region,string_types)) for s in content))
     self.content=content
@@ -70,13 +72,69 @@
 
   def addRegion(self,content):
     assert(isinstance(content,(Region,string_types)))
+    # convert
     self.content.append(content)
 
+cell=r'(\$?)([A-Z]+)(\$?)([1-9][0-9]*)'
+RANGE=re.compile(cell+(r'(:%s)?'%cell))
+C=0 # Column
+R=1 # Row
+F=0 # Fixed ($)
+V=1 # Value
+@to_object()
+class Range(object):
+  def __init__(self,estr):
+    m=RANGE.match(estr)
+    if m is None:
+      raise ValueError("string %s doesn't represent a range"%estr)
+    rgrps=m.groups()
+    self.tl=((rgrps[0]=='$',rgrps[1]),((rgrps[2]=='$',int(rgrps[3]))))
+    if rgrps[4] is None:
+      self.br=None
+      self.dim=0
+      self.vertical=None
+    else:
+      self.br=((rgrps[5]=='$',rgrps[6]),((rgrps[7]=='$',int(rgrps[8]))))
+      if self.tl[C][V]==self.br[C][V]:
+        self.dim=1
+        self.vertical=True
+      elif self.tl[R][V]==self.br[R][V]:
+        self.dim=1
+        self.vertical=False
+      else:
+        self.dim=2
+        self.vertical=None
+
+  def __str__(self):
+    tls=_cellStr(self.tl[C])+_cellStr(self.tl[R])
+    if self.br is None:
+      return tls
+    else:
+      return '%s:%s'%(tls,_cellStr(self.br[C])+_cellStr(self.br[R]))
+
+def _cellStr(dvp):
+  (dollar,val)=dvp
+  return '%s%s'%('$' if dollar else '',str(val))
+
+@from_object()
+@to_object(exclude_nulls=True)
+class M(Region):
+  def __init__(self,name,sheet=None,ranges=[],labels=[],data=[]):
+    super(M,self).__init__(name,sheet,ranges,labels,data)
+
+@from_object()
+@to_object(exclude_nulls=True)
+class RC(Region):
+  def __init__(self,name,sheet=None,ranges=[],labels=[],data=[]):
+    super(RC,self).__init__(name,sheet,ranges,labels,data)
+
 @from_object()
 @to_object(exclude_nulls=True,suppress=["sheet"])
-class Table(Region):
-  def __init__(self,name,sheet=None,ranges=[],labels=[],data=[]):
+class Table(M):
+  def __init__(self,name,shape='mixed',sheet=None,ranges=[],labels=[],data=[]):
     super(Table,self).__init__(name,sheet,ranges)
+    assert(shape in ('columns','rows','mixed'))
+    self.shape=shape # if columns or rows, that's what correspond to DB columns
     labels=list(labels)
     assert(all(isinstance(s,Label) for s in labels))
     self.labels=labels
@@ -105,4 +163,4 @@
 
 def lt(filename):
   with open(filename,'r') as js:
-    return json.loads(js.read(),cls=eDecoder.eDecoder)
+    return loader(js.read(),cls=eDecoder.eDecoder)