data_source.py 5.6 KB

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