forked from Alsan/Post_finder
207 lines
5.3 KiB
Python
207 lines
5.3 KiB
Python
# Copyright (c) 2010-2024 openpyxl
|
|
|
|
from array import array
|
|
|
|
from openpyxl.descriptors.serialisable import Serialisable
|
|
from openpyxl.descriptors import (
|
|
Typed,
|
|
Float,
|
|
Bool,
|
|
Integer,
|
|
Sequence,
|
|
)
|
|
from openpyxl.descriptors.excel import ExtensionList
|
|
from openpyxl.utils.indexed_list import IndexedList
|
|
|
|
|
|
from .alignment import Alignment
|
|
from .protection import Protection
|
|
|
|
|
|
class ArrayDescriptor:
|
|
|
|
def __init__(self, key):
|
|
self.key = key
|
|
|
|
def __get__(self, instance, cls):
|
|
return instance[self.key]
|
|
|
|
def __set__(self, instance, value):
|
|
instance[self.key] = value
|
|
|
|
|
|
class StyleArray(array):
|
|
"""
|
|
Simplified named tuple with an array
|
|
"""
|
|
|
|
__slots__ = ()
|
|
tagname = 'xf'
|
|
|
|
fontId = ArrayDescriptor(0)
|
|
fillId = ArrayDescriptor(1)
|
|
borderId = ArrayDescriptor(2)
|
|
numFmtId = ArrayDescriptor(3)
|
|
protectionId = ArrayDescriptor(4)
|
|
alignmentId = ArrayDescriptor(5)
|
|
pivotButton = ArrayDescriptor(6)
|
|
quotePrefix = ArrayDescriptor(7)
|
|
xfId = ArrayDescriptor(8)
|
|
|
|
|
|
def __new__(cls, args=[0]*9):
|
|
return array.__new__(cls, 'i', args)
|
|
|
|
|
|
def __hash__(self):
|
|
return hash(tuple(self))
|
|
|
|
|
|
def __copy__(self):
|
|
return StyleArray((self))
|
|
|
|
|
|
def __deepcopy__(self, memo):
|
|
return StyleArray((self))
|
|
|
|
|
|
class CellStyle(Serialisable):
|
|
|
|
tagname = "xf"
|
|
|
|
numFmtId = Integer()
|
|
fontId = Integer()
|
|
fillId = Integer()
|
|
borderId = Integer()
|
|
xfId = Integer(allow_none=True)
|
|
quotePrefix = Bool(allow_none=True)
|
|
pivotButton = Bool(allow_none=True)
|
|
applyNumberFormat = Bool(allow_none=True)
|
|
applyFont = Bool(allow_none=True)
|
|
applyFill = Bool(allow_none=True)
|
|
applyBorder = Bool(allow_none=True)
|
|
applyAlignment = Bool(allow_none=True)
|
|
applyProtection = Bool(allow_none=True)
|
|
alignment = Typed(expected_type=Alignment, allow_none=True)
|
|
protection = Typed(expected_type=Protection, allow_none=True)
|
|
extLst = Typed(expected_type=ExtensionList, allow_none=True)
|
|
|
|
__elements__ = ('alignment', 'protection')
|
|
__attrs__ = ("numFmtId", "fontId", "fillId", "borderId",
|
|
"applyAlignment", "applyProtection", "pivotButton", "quotePrefix", "xfId")
|
|
|
|
def __init__(self,
|
|
numFmtId=0,
|
|
fontId=0,
|
|
fillId=0,
|
|
borderId=0,
|
|
xfId=None,
|
|
quotePrefix=None,
|
|
pivotButton=None,
|
|
applyNumberFormat=None,
|
|
applyFont=None,
|
|
applyFill=None,
|
|
applyBorder=None,
|
|
applyAlignment=None,
|
|
applyProtection=None,
|
|
alignment=None,
|
|
protection=None,
|
|
extLst=None,
|
|
):
|
|
self.numFmtId = numFmtId
|
|
self.fontId = fontId
|
|
self.fillId = fillId
|
|
self.borderId = borderId
|
|
self.xfId = xfId
|
|
self.quotePrefix = quotePrefix
|
|
self.pivotButton = pivotButton
|
|
self.applyNumberFormat = applyNumberFormat
|
|
self.applyFont = applyFont
|
|
self.applyFill = applyFill
|
|
self.applyBorder = applyBorder
|
|
self.alignment = alignment
|
|
self.protection = protection
|
|
|
|
|
|
def to_array(self):
|
|
"""
|
|
Convert to StyleArray
|
|
"""
|
|
style = StyleArray()
|
|
for k in ("fontId", "fillId", "borderId", "numFmtId", "pivotButton",
|
|
"quotePrefix", "xfId"):
|
|
v = getattr(self, k, 0)
|
|
if v is not None:
|
|
setattr(style, k, v)
|
|
return style
|
|
|
|
|
|
@classmethod
|
|
def from_array(cls, style):
|
|
"""
|
|
Convert from StyleArray
|
|
"""
|
|
return cls(numFmtId=style.numFmtId, fontId=style.fontId,
|
|
fillId=style.fillId, borderId=style.borderId, xfId=style.xfId,
|
|
quotePrefix=style.quotePrefix, pivotButton=style.pivotButton,)
|
|
|
|
|
|
@property
|
|
def applyProtection(self):
|
|
return self.protection is not None or None
|
|
|
|
|
|
@property
|
|
def applyAlignment(self):
|
|
return self.alignment is not None or None
|
|
|
|
|
|
class CellStyleList(Serialisable):
|
|
|
|
tagname = "cellXfs"
|
|
|
|
__attrs__ = ("count",)
|
|
|
|
count = Integer(allow_none=True)
|
|
xf = Sequence(expected_type=CellStyle)
|
|
alignment = Sequence(expected_type=Alignment)
|
|
protection = Sequence(expected_type=Protection)
|
|
|
|
__elements__ = ('xf',)
|
|
|
|
def __init__(self,
|
|
count=None,
|
|
xf=(),
|
|
):
|
|
self.xf = xf
|
|
|
|
|
|
@property
|
|
def count(self):
|
|
return len(self.xf)
|
|
|
|
|
|
def __getitem__(self, idx):
|
|
try:
|
|
return self.xf[idx]
|
|
except IndexError:
|
|
print((f"{idx} is out of range"))
|
|
return self.xf[idx]
|
|
|
|
|
|
def _to_array(self):
|
|
"""
|
|
Extract protection and alignments, convert to style array
|
|
"""
|
|
self.prots = IndexedList([Protection()])
|
|
self.alignments = IndexedList([Alignment()])
|
|
styles = [] # allow duplicates
|
|
for xf in self.xf:
|
|
style = xf.to_array()
|
|
if xf.alignment is not None:
|
|
style.alignmentId = self.alignments.add(xf.alignment)
|
|
if xf.protection is not None:
|
|
style.protectionId = self.prots.add(xf.protection)
|
|
styles.append(style)
|
|
return IndexedList(styles)
|