113 lines
2.4 KiB
Python
113 lines
2.4 KiB
Python
# 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
|
|
|
|
|
|
class HexBinary(MatchPattern):
|
|
|
|
pattern = "[0-9a-fA-F]+$"
|
|
|
|
|
|
class UniversalMeasure(MatchPattern):
|
|
|
|
pattern = r"[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)"
|
|
|
|
|
|
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
|
|
|
|
|
|
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)
|
|
|
|
|
|
class Extension(Serialisable):
|
|
|
|
uri = String()
|
|
|
|
def __init__(self,
|
|
uri=None,
|
|
):
|
|
self.uri = uri
|
|
|
|
|
|
class ExtensionList(Serialisable):
|
|
|
|
ext = Sequence(expected_type=Extension)
|
|
|
|
def __init__(self,
|
|
ext=(),
|
|
):
|
|
self.ext = ext
|
|
|
|
|
|
class Relation(String):
|
|
|
|
namespace = REL_NS
|
|
allow_none = True
|
|
|
|
|
|
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})$"
|
|
|
|
|
|
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}\}"
|
|
|
|
|
|
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))
|