Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/openpyxl/workbook/defined_name.py: 31%
145 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1# Copyright (c) 2010-2022 openpyxl
3import re
5from openpyxl.descriptors.serialisable import Serialisable
6from openpyxl.descriptors import (
7 Alias,
8 Typed,
9 String,
10 Float,
11 Integer,
12 Bool,
13 NoneSet,
14 Set,
15 Sequence,
16 Descriptor,
17)
18from openpyxl.compat import safe_string
19from openpyxl.formula import Tokenizer
20from openpyxl.utils.cell import (
21 SHEETRANGE_RE,
22 SHEET_TITLE,
23)
25RESERVED = frozenset(["Print_Area", "Print_Titles", "Criteria",
26 "_FilterDatabase", "Extract", "Consolidate_Area",
27 "Sheet_Title"])
29_names = "|".join(RESERVED)
30RESERVED_REGEX = re.compile(r"^_xlnm\.(?P<name>{0})".format(_names))
31COL_RANGE = r"""(?P<cols>[$]?[a-zA-Z]{1,3}:[$]?[a-zA-Z]{1,3})"""
32COL_RANGE_RE = re.compile(COL_RANGE)
33ROW_RANGE = r"""(?P<rows>[$]?\d+:[$]?\d+)"""
34ROW_RANGE_RE = re.compile(ROW_RANGE)
35TITLES_REGEX = re.compile("""{0}{1}?,?{2}?""".format(SHEET_TITLE, ROW_RANGE, COL_RANGE),
36 re.VERBOSE)
39### utilities
41def _unpack_print_titles(defn):
42 """
43 Extract rows and or columns from print titles so that they can be
44 assigned to a worksheet
45 """
46 scanner = TITLES_REGEX.finditer(defn.value)
47 kw = dict((k, v) for match in scanner
48 for k, v in match.groupdict().items() if v)
50 return kw.get('rows'), kw.get('cols')
53def _unpack_print_area(defn):
54 """
55 Extract print area
56 """
57 new = []
58 for m in SHEETRANGE_RE.finditer(defn.value): # can be multiple
59 coord = m.group("cells")
60 if coord:
61 new.append(coord)
62 return new
65class DefinedName(Serialisable):
67 tagname = "definedName"
69 name = String() # unique per workbook/worksheet
70 comment = String(allow_none=True)
71 customMenu = String(allow_none=True)
72 description = String(allow_none=True)
73 help = String(allow_none=True)
74 statusBar = String(allow_none=True)
75 localSheetId = Integer(allow_none=True)
76 hidden = Bool(allow_none=True)
77 function = Bool(allow_none=True)
78 vbProcedure = Bool(allow_none=True)
79 xlm = Bool(allow_none=True)
80 functionGroupId = Integer(allow_none=True)
81 shortcutKey = String(allow_none=True)
82 publishToServer = Bool(allow_none=True)
83 workbookParameter = Bool(allow_none=True)
84 attr_text = Descriptor()
85 value = Alias("attr_text")
88 def __init__(self,
89 name=None,
90 comment=None,
91 customMenu=None,
92 description=None,
93 help=None,
94 statusBar=None,
95 localSheetId=None,
96 hidden=None,
97 function=None,
98 vbProcedure=None,
99 xlm=None,
100 functionGroupId=None,
101 shortcutKey=None,
102 publishToServer=None,
103 workbookParameter=None,
104 attr_text=None
105 ):
106 self.name = name
107 self.comment = comment
108 self.customMenu = customMenu
109 self.description = description
110 self.help = help
111 self.statusBar = statusBar
112 self.localSheetId = localSheetId
113 self.hidden = hidden
114 self.function = function
115 self.vbProcedure = vbProcedure
116 self.xlm = xlm
117 self.functionGroupId = functionGroupId
118 self.shortcutKey = shortcutKey
119 self.publishToServer = publishToServer
120 self.workbookParameter = workbookParameter
121 self.attr_text = attr_text
124 @property
125 def type(self):
126 tok = Tokenizer("=" + self.value)
127 parsed = tok.items[0]
128 if parsed.type == "OPERAND":
129 return parsed.subtype
130 return parsed.type
133 @property
134 def destinations(self):
135 if self.type == "RANGE":
136 tok = Tokenizer("=" + self.value)
137 for part in tok.items:
138 if part.subtype == "RANGE":
139 m = SHEETRANGE_RE.match(part.value)
140 sheetname = m.group('notquoted') or m.group('quoted')
141 yield sheetname, m.group('cells')
144 @property
145 def is_reserved(self):
146 m = RESERVED_REGEX.match(self.name)
147 if m:
148 return m.group("name")
151 @property
152 def is_external(self):
153 return re.compile(r"^\[\d+\].*").match(self.value) is not None
156 def __iter__(self):
157 for key in self.__attrs__:
158 if key == "attr_text":
159 continue
160 v = getattr(self, key)
161 if v is not None:
162 if v in RESERVED:
163 v = "_xlnm." + v
164 yield key, safe_string(v)
167class DefinedNameList(Serialisable):
169 tagname = "definedNames"
171 definedName = Sequence(expected_type=DefinedName)
174 def __init__(self, definedName=()):
175 self.definedName = definedName
178 def _cleanup(self):
179 """
180 Strip invalid definitions and remove special hidden ones
181 """
182 valid_names = []
183 for n in self.definedName:
184 if n.name in ("_xlnm.Print_Titles", "_xlnm.Print_Area") and n.localSheetId is None:
185 continue
186 elif n.name == "_xlnm._FilterDatabase":
187 continue
188 valid_names.append(n)
189 self.definedName = valid_names
192 def _duplicate(self, defn):
193 """
194 Check for whether DefinedName with the same name and scope already
195 exists
196 """
197 for d in self.definedName:
198 if d.name == defn.name and d.localSheetId == defn.localSheetId:
199 return True
202 def append(self, defn):
203 if not isinstance(defn, DefinedName):
204 raise TypeError("""You can only append DefinedNames""")
205 if self._duplicate(defn):
206 raise ValueError("""DefinedName with the same name and scope already exists""")
207 names = self.definedName[:]
208 names.append(defn)
209 self.definedName = names
212 def __len__(self):
213 return len(self.definedName)
216 def __contains__(self, name):
217 """
218 See if a globaly defined name exists
219 """
220 for defn in self.definedName:
221 if defn.name == name and defn.localSheetId is None:
222 return True
225 def __getitem__(self, name):
226 """
227 Get globally defined name
228 """
229 defn = self.get(name)
230 if not defn:
231 raise KeyError("No definition called {0}".format(name))
232 return defn
235 def get(self, name, scope=None):
236 """
237 Get the name assigned to a specicic sheet or global
238 """
239 for defn in self.definedName:
240 if defn.name == name and defn.localSheetId == scope:
241 return defn
244 def __delitem__(self, name):
245 """
246 Delete a globally defined name
247 """
248 if not self.delete(name):
249 raise KeyError("No globally defined name {0}".format(name))
252 def delete(self, name, scope=None):
253 """
254 Delete a name assigned to a specific or global
255 """
256 for idx, defn in enumerate(self.definedName):
257 if defn.name == name and defn.localSheetId == scope:
258 del self.definedName[idx]
259 return True
262 def localnames(self, scope):
263 """
264 Provide a list of all names for a particular worksheet
265 """
266 return [defn.name for defn in self.definedName if defn.localSheetId == scope]