| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- # Copyright (c) 2010-2024 openpyxl
- from collections import defaultdict
- import re
- from openpyxl.descriptors.serialisable import Serialisable
- from openpyxl.descriptors import (
- Alias,
- String,
- Integer,
- Bool,
- Sequence,
- Descriptor,
- )
- from openpyxl.compat import safe_string
- from openpyxl.formula import Tokenizer
- from openpyxl.utils.cell import SHEETRANGE_RE
- RESERVED = frozenset(["Print_Area", "Print_Titles", "Criteria",
- "_FilterDatabase", "Extract", "Consolidate_Area",
- "Sheet_Title"])
- _names = "|".join(RESERVED)
- RESERVED_REGEX = re.compile(r"^_xlnm\.(?P<name>{0})".format(_names))
- class DefinedName(Serialisable):
- tagname = "definedName"
- name = String() # unique per workbook/worksheet
- comment = String(allow_none=True)
- customMenu = String(allow_none=True)
- description = String(allow_none=True)
- help = String(allow_none=True)
- statusBar = String(allow_none=True)
- localSheetId = Integer(allow_none=True)
- hidden = Bool(allow_none=True)
- function = Bool(allow_none=True)
- vbProcedure = Bool(allow_none=True)
- xlm = Bool(allow_none=True)
- functionGroupId = Integer(allow_none=True)
- shortcutKey = String(allow_none=True)
- publishToServer = Bool(allow_none=True)
- workbookParameter = Bool(allow_none=True)
- attr_text = Descriptor()
- value = Alias("attr_text")
- def __init__(self,
- name=None,
- comment=None,
- customMenu=None,
- description=None,
- help=None,
- statusBar=None,
- localSheetId=None,
- hidden=None,
- function=None,
- vbProcedure=None,
- xlm=None,
- functionGroupId=None,
- shortcutKey=None,
- publishToServer=None,
- workbookParameter=None,
- attr_text=None
- ):
- self.name = name
- self.comment = comment
- self.customMenu = customMenu
- self.description = description
- self.help = help
- self.statusBar = statusBar
- self.localSheetId = localSheetId
- self.hidden = hidden
- self.function = function
- self.vbProcedure = vbProcedure
- self.xlm = xlm
- self.functionGroupId = functionGroupId
- self.shortcutKey = shortcutKey
- self.publishToServer = publishToServer
- self.workbookParameter = workbookParameter
- self.attr_text = attr_text
- @property
- def type(self):
- tok = Tokenizer("=" + self.value)
- parsed = tok.items[0]
- if parsed.type == "OPERAND":
- return parsed.subtype
- return parsed.type
- @property
- def destinations(self):
- if self.type == "RANGE":
- tok = Tokenizer("=" + self.value)
- for part in tok.items:
- if part.subtype == "RANGE":
- m = SHEETRANGE_RE.match(part.value)
- sheetname = m.group('notquoted') or m.group('quoted')
- yield sheetname, m.group('cells')
- @property
- def is_reserved(self):
- m = RESERVED_REGEX.match(self.name)
- if m:
- return m.group("name")
- @property
- def is_external(self):
- return re.compile(r"^\[\d+\].*").match(self.value) is not None
- def __iter__(self):
- for key in self.__attrs__:
- if key == "attr_text":
- continue
- v = getattr(self, key)
- if v is not None:
- if v in RESERVED:
- v = "_xlnm." + v
- yield key, safe_string(v)
- class DefinedNameDict(dict):
- """
- Utility class for storing defined names.
- Allows access by name and separation of global and scoped names
- """
- def __setitem__(self, key, value):
- if not isinstance(value, DefinedName):
- raise TypeError("Value must be a an instance of DefinedName")
- elif value.name != key:
- raise ValueError("Key must be the same as the name")
- super().__setitem__(key, value)
- def add(self, value):
- """
- Add names without worrying about key and name matching.
- """
- self[value.name] = value
- class DefinedNameList(Serialisable):
- tagname = "definedNames"
- definedName = Sequence(expected_type=DefinedName)
- def __init__(self, definedName=()):
- self.definedName = definedName
- def by_sheet(self):
- """
- Break names down into sheet locals and globals
- """
- names = defaultdict(DefinedNameDict)
- for defn in self.definedName:
- if defn.localSheetId is None:
- if defn.name in ("_xlnm.Print_Titles", "_xlnm.Print_Area", "_xlnm._FilterDatabase"):
- continue
- names["global"][defn.name] = defn
- else:
- sheet = int(defn.localSheetId)
- names[sheet][defn.name] = defn
- return names
- def _duplicate(self, defn):
- """
- Check for whether DefinedName with the same name and scope already
- exists
- """
- for d in self.definedName:
- if d.name == defn.name and d.localSheetId == defn.localSheetId:
- return True
- def __len__(self):
- return len(self.definedName)
|