1"""
2Collection of utility primitives for charts.
3"""
4
5from openpyxl.descriptors.serialisable import Serialisable
6from openpyxl.descriptors import (
7 Bool,
8 Typed,
9 Alias,
10 String,
11 Integer,
12 Sequence,
13)
14from openpyxl.descriptors.excel import ExtensionList
15from openpyxl.descriptors.nested import (
16 NestedString,
17 NestedText,
18 NestedInteger,
19)
20
21
22class NumFmt(Serialisable):
23
24 formatCode = String()
25 sourceLinked = Bool()
26
27 def __init__(self,
28 formatCode=None,
29 sourceLinked=False
30 ):
31 self.formatCode = formatCode
32 self.sourceLinked = sourceLinked
33
34
35class NumberValueDescriptor(NestedText):
36 """
37 Data should be numerical but isn't always :-/
38 """
39
40 allow_none = True
41
42 def __set__(self, instance, value):
43 if value == "#N/A":
44 self.expected_type = str
45 else:
46 self.expected_type = float
47 super().__set__(instance, value)
48
49
50class NumVal(Serialisable):
51
52 idx = Integer()
53 formatCode = NestedText(allow_none=True, expected_type=str)
54 v = NumberValueDescriptor()
55
56 def __init__(self,
57 idx=None,
58 formatCode=None,
59 v=None,
60 ):
61 self.idx = idx
62 self.formatCode = formatCode
63 self.v = v
64
65
66class NumData(Serialisable):
67
68 formatCode = NestedText(expected_type=str, allow_none=True)
69 ptCount = NestedInteger(allow_none=True)
70 pt = Sequence(expected_type=NumVal)
71 extLst = Typed(expected_type=ExtensionList, allow_none=True)
72
73 __elements__ = ('formatCode', 'ptCount', 'pt')
74
75 def __init__(self,
76 formatCode=None,
77 ptCount=None,
78 pt=(),
79 extLst=None,
80 ):
81 self.formatCode = formatCode
82 self.ptCount = ptCount
83 self.pt = pt
84
85
86class NumRef(Serialisable):
87
88 f = NestedText(expected_type=str)
89 ref = Alias('f')
90 numCache = Typed(expected_type=NumData, allow_none=True)
91 extLst = Typed(expected_type=ExtensionList, allow_none=True)
92
93 __elements__ = ('f', 'numCache')
94
95 def __init__(self,
96 f=None,
97 numCache=None,
98 extLst=None,
99 ):
100 self.f = f
101 self.numCache = numCache
102
103
104class StrVal(Serialisable):
105
106 tagname = "strVal"
107
108 idx = Integer()
109 v = NestedText(expected_type=str)
110
111 def __init__(self,
112 idx=0,
113 v=None,
114 ):
115 self.idx = idx
116 self.v = v
117
118
119class StrData(Serialisable):
120
121 tagname = "strData"
122
123 ptCount = NestedInteger(allow_none=True)
124 pt = Sequence(expected_type=StrVal)
125 extLst = Typed(expected_type=ExtensionList, allow_none=True)
126
127 __elements__ = ('ptCount', 'pt')
128
129 def __init__(self,
130 ptCount=None,
131 pt=(),
132 extLst=None,
133 ):
134 self.ptCount = ptCount
135 self.pt = pt
136
137
138class StrRef(Serialisable):
139
140 tagname = "strRef"
141
142 f = NestedText(expected_type=str, allow_none=True)
143 strCache = Typed(expected_type=StrData, allow_none=True)
144 extLst = Typed(expected_type=ExtensionList, allow_none=True)
145
146 __elements__ = ('f', 'strCache')
147
148 def __init__(self,
149 f=None,
150 strCache=None,
151 extLst=None,
152 ):
153 self.f = f
154 self.strCache = strCache
155
156
157class NumDataSource(Serialisable):
158
159 numRef = Typed(expected_type=NumRef, allow_none=True)
160 numLit = Typed(expected_type=NumData, allow_none=True)
161
162
163 def __init__(self,
164 numRef=None,
165 numLit=None,
166 ):
167 self.numRef = numRef
168 self.numLit = numLit
169
170
171class Level(Serialisable):
172
173 tagname = "lvl"
174
175 pt = Sequence(expected_type=StrVal)
176
177 __elements__ = ('pt',)
178
179 def __init__(self,
180 pt=(),
181 ):
182 self.pt = pt
183
184
185class MultiLevelStrData(Serialisable):
186
187 tagname = "multiLvlStrData"
188
189 ptCount = Integer(allow_none=True)
190 lvl = Sequence(expected_type=Level)
191 extLst = Typed(expected_type=ExtensionList, allow_none=True)
192
193 __elements__ = ('ptCount', 'lvl',)
194
195 def __init__(self,
196 ptCount=None,
197 lvl=(),
198 extLst=None,
199 ):
200 self.ptCount = ptCount
201 self.lvl = lvl
202
203
204class MultiLevelStrRef(Serialisable):
205
206 tagname = "multiLvlStrRef"
207
208 f = NestedText(expected_type=str)
209 multiLvlStrCache = Typed(expected_type=MultiLevelStrData, allow_none=True)
210 extLst = Typed(expected_type=ExtensionList, allow_none=True)
211
212 __elements__ = ('multiLvlStrCache', 'f')
213
214 def __init__(self,
215 f=None,
216 multiLvlStrCache=None,
217 extLst=None,
218 ):
219 self.f = f
220 self.multiLvlStrCache = multiLvlStrCache
221
222
223class AxDataSource(Serialisable):
224
225 tagname = "cat"
226
227 numRef = Typed(expected_type=NumRef, allow_none=True)
228 numLit = Typed(expected_type=NumData, allow_none=True)
229 strRef = Typed(expected_type=StrRef, allow_none=True)
230 strLit = Typed(expected_type=StrData, allow_none=True)
231 multiLvlStrRef = Typed(expected_type=MultiLevelStrRef, allow_none=True)
232
233 def __init__(self,
234 numRef=None,
235 numLit=None,
236 strRef=None,
237 strLit=None,
238 multiLvlStrRef=None,
239 ):
240 if not any([numLit, numRef, strRef, strLit, multiLvlStrRef]):
241 raise TypeError("A data source must be provided")
242 self.numRef = numRef
243 self.numLit = numLit
244 self.strRef = strRef
245 self.strLit = strLit
246 self.multiLvlStrRef = multiLvlStrRef