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

1# Copyright (c) 2010-2022 openpyxl 

2 

3import re 

4 

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) 

24 

25RESERVED = frozenset(["Print_Area", "Print_Titles", "Criteria", 

26 "_FilterDatabase", "Extract", "Consolidate_Area", 

27 "Sheet_Title"]) 

28 

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) 

37 

38 

39### utilities 

40 

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) 

49 

50 return kw.get('rows'), kw.get('cols') 

51 

52 

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 

63 

64 

65class DefinedName(Serialisable): 

66 

67 tagname = "definedName" 

68 

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") 

86 

87 

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 

122 

123 

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 

131 

132 

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') 

142 

143 

144 @property 

145 def is_reserved(self): 

146 m = RESERVED_REGEX.match(self.name) 

147 if m: 

148 return m.group("name") 

149 

150 

151 @property 

152 def is_external(self): 

153 return re.compile(r"^\[\d+\].*").match(self.value) is not None 

154 

155 

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) 

165 

166 

167class DefinedNameList(Serialisable): 

168 

169 tagname = "definedNames" 

170 

171 definedName = Sequence(expected_type=DefinedName) 

172 

173 

174 def __init__(self, definedName=()): 

175 self.definedName = definedName 

176 

177 

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 

190 

191 

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 

200 

201 

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 

210 

211 

212 def __len__(self): 

213 return len(self.definedName) 

214 

215 

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 

223 

224 

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 

233 

234 

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 

242 

243 

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)) 

250 

251 

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 

260 

261 

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]