# Copyright (c) 2010-2024 openpyxl
"""
Excel specific descriptors
"""
from openpyxl.xml.constants import REL_NS
from openpyxl.compat import safe_string
from openpyxl.xml.functions import Element
from . import (
MatchPattern,
MinMax,
Integer,
String,
Sequence,
)
from .serialisable import Serialisable
[docs]
class HexBinary(MatchPattern):
pattern = "[0-9a-fA-F]+$"
[docs]
class UniversalMeasure(MatchPattern):
pattern = r"[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"
[docs]
class TextPoint(MinMax):
"""
Size in hundredths of points.
In theory other units of measurement can be used but these are unbounded
"""
expected_type = int
min = -400000
max = 400000
Coordinate = Integer
[docs]
class Percentage(MinMax):
pattern = r"((100)|([0-9][0-9]?))(\.[0-9][0-9]?)?%" # strict
min = -1000000
max = 1000000
def __set__(self, instance, value):
if isinstance(value, str) and "%" in value:
value = value.replace("%", "")
value = int(float(value) * 1000)
super().__set__(instance, value)
[docs]
class Extension(Serialisable):
uri = String()
def __init__(self,
uri=None,
):
self.uri = uri
[docs]
class ExtensionList(Serialisable):
ext = Sequence(expected_type=Extension)
def __init__(self,
ext=(),
):
self.ext = ext
[docs]
class Relation(String):
namespace = REL_NS
allow_none = True
[docs]
class Base64Binary(MatchPattern):
# http://www.w3.org/TR/xmlschema11-2/#nt-Base64Binary
pattern = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$"
[docs]
class Guid(MatchPattern):
# https://msdn.microsoft.com/en-us/library/dd946381(v=office.12).aspx
pattern = r"{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}"
[docs]
class CellRange(MatchPattern):
pattern = r"^[$]?([A-Za-z]{1,3})[$]?(\d+)(:[$]?([A-Za-z]{1,3})[$]?(\d+)?)?$|^[A-Za-z]{1,3}:[A-Za-z]{1,3}$"
allow_none = True
def __set__(self, instance, value):
if value is not None:
value = value.upper()
super().__set__(instance, value)
def _explicit_none(tagname, value, namespace=None):
"""
Override serialisation because explicit none required
"""
if namespace is not None:
tagname = "{%s}%s" % (namespace, tagname)
return Element(tagname, val=safe_string(value))