Updated script that can be controled by Nodejs web app
This commit is contained in:
291
lib/python3.13/site-packages/openpyxl/formatting/rule.py
Normal file
291
lib/python3.13/site-packages/openpyxl/formatting/rule.py
Normal file
@ -0,0 +1,291 @@
|
||||
# Copyright (c) 2010-2024 openpyxl
|
||||
|
||||
from openpyxl.descriptors.serialisable import Serialisable
|
||||
from openpyxl.descriptors import (
|
||||
Typed,
|
||||
String,
|
||||
Sequence,
|
||||
Bool,
|
||||
NoneSet,
|
||||
Set,
|
||||
Integer,
|
||||
Float,
|
||||
)
|
||||
from openpyxl.descriptors.excel import ExtensionList
|
||||
from openpyxl.styles.colors import Color, ColorDescriptor
|
||||
from openpyxl.styles.differential import DifferentialStyle
|
||||
|
||||
from openpyxl.utils.cell import COORD_RE
|
||||
|
||||
|
||||
class ValueDescriptor(Float):
|
||||
"""
|
||||
Expected type depends upon type attribute of parent :-(
|
||||
|
||||
Most values should be numeric BUT they can also be cell references
|
||||
"""
|
||||
|
||||
def __set__(self, instance, value):
|
||||
ref = None
|
||||
if value is not None and isinstance(value, str):
|
||||
ref = COORD_RE.match(value)
|
||||
if instance.type == "formula" or ref:
|
||||
self.expected_type = str
|
||||
else:
|
||||
self.expected_type = float
|
||||
super().__set__(instance, value)
|
||||
|
||||
|
||||
class FormatObject(Serialisable):
|
||||
|
||||
tagname = "cfvo"
|
||||
|
||||
type = Set(values=(['num', 'percent', 'max', 'min', 'formula', 'percentile']))
|
||||
val = ValueDescriptor(allow_none=True)
|
||||
gte = Bool(allow_none=True)
|
||||
extLst = Typed(expected_type=ExtensionList, allow_none=True)
|
||||
|
||||
__elements__ = ()
|
||||
|
||||
def __init__(self,
|
||||
type,
|
||||
val=None,
|
||||
gte=None,
|
||||
extLst=None,
|
||||
):
|
||||
self.type = type
|
||||
self.val = val
|
||||
self.gte = gte
|
||||
|
||||
|
||||
class RuleType(Serialisable):
|
||||
|
||||
cfvo = Sequence(expected_type=FormatObject)
|
||||
|
||||
|
||||
class IconSet(RuleType):
|
||||
|
||||
tagname = "iconSet"
|
||||
|
||||
iconSet = NoneSet(values=(['3Arrows', '3ArrowsGray', '3Flags',
|
||||
'3TrafficLights1', '3TrafficLights2', '3Signs', '3Symbols', '3Symbols2',
|
||||
'4Arrows', '4ArrowsGray', '4RedToBlack', '4Rating', '4TrafficLights',
|
||||
'5Arrows', '5ArrowsGray', '5Rating', '5Quarters']))
|
||||
showValue = Bool(allow_none=True)
|
||||
percent = Bool(allow_none=True)
|
||||
reverse = Bool(allow_none=True)
|
||||
|
||||
__elements__ = ("cfvo",)
|
||||
|
||||
def __init__(self,
|
||||
iconSet=None,
|
||||
showValue=None,
|
||||
percent=None,
|
||||
reverse=None,
|
||||
cfvo=None,
|
||||
):
|
||||
self.iconSet = iconSet
|
||||
self.showValue = showValue
|
||||
self.percent = percent
|
||||
self.reverse = reverse
|
||||
self.cfvo = cfvo
|
||||
|
||||
|
||||
class DataBar(RuleType):
|
||||
|
||||
tagname = "dataBar"
|
||||
|
||||
minLength = Integer(allow_none=True)
|
||||
maxLength = Integer(allow_none=True)
|
||||
showValue = Bool(allow_none=True)
|
||||
color = ColorDescriptor()
|
||||
|
||||
__elements__ = ('cfvo', 'color')
|
||||
|
||||
def __init__(self,
|
||||
minLength=None,
|
||||
maxLength=None,
|
||||
showValue=None,
|
||||
cfvo=None,
|
||||
color=None,
|
||||
):
|
||||
self.minLength = minLength
|
||||
self.maxLength = maxLength
|
||||
self.showValue = showValue
|
||||
self.cfvo = cfvo
|
||||
self.color = color
|
||||
|
||||
|
||||
class ColorScale(RuleType):
|
||||
|
||||
tagname = "colorScale"
|
||||
|
||||
color = Sequence(expected_type=Color)
|
||||
|
||||
__elements__ = ('cfvo', 'color')
|
||||
|
||||
def __init__(self,
|
||||
cfvo=None,
|
||||
color=None,
|
||||
):
|
||||
self.cfvo = cfvo
|
||||
self.color = color
|
||||
|
||||
|
||||
class Rule(Serialisable):
|
||||
|
||||
tagname = "cfRule"
|
||||
|
||||
type = Set(values=(['expression', 'cellIs', 'colorScale', 'dataBar',
|
||||
'iconSet', 'top10', 'uniqueValues', 'duplicateValues', 'containsText',
|
||||
'notContainsText', 'beginsWith', 'endsWith', 'containsBlanks',
|
||||
'notContainsBlanks', 'containsErrors', 'notContainsErrors', 'timePeriod',
|
||||
'aboveAverage']))
|
||||
dxfId = Integer(allow_none=True)
|
||||
priority = Integer()
|
||||
stopIfTrue = Bool(allow_none=True)
|
||||
aboveAverage = Bool(allow_none=True)
|
||||
percent = Bool(allow_none=True)
|
||||
bottom = Bool(allow_none=True)
|
||||
operator = NoneSet(values=(['lessThan', 'lessThanOrEqual', 'equal',
|
||||
'notEqual', 'greaterThanOrEqual', 'greaterThan', 'between', 'notBetween',
|
||||
'containsText', 'notContains', 'beginsWith', 'endsWith']))
|
||||
text = String(allow_none=True)
|
||||
timePeriod = NoneSet(values=(['today', 'yesterday', 'tomorrow', 'last7Days',
|
||||
'thisMonth', 'lastMonth', 'nextMonth', 'thisWeek', 'lastWeek',
|
||||
'nextWeek']))
|
||||
rank = Integer(allow_none=True)
|
||||
stdDev = Integer(allow_none=True)
|
||||
equalAverage = Bool(allow_none=True)
|
||||
formula = Sequence(expected_type=str)
|
||||
colorScale = Typed(expected_type=ColorScale, allow_none=True)
|
||||
dataBar = Typed(expected_type=DataBar, allow_none=True)
|
||||
iconSet = Typed(expected_type=IconSet, allow_none=True)
|
||||
extLst = Typed(expected_type=ExtensionList, allow_none=True)
|
||||
dxf = Typed(expected_type=DifferentialStyle, allow_none=True)
|
||||
|
||||
__elements__ = ('colorScale', 'dataBar', 'iconSet', 'formula')
|
||||
__attrs__ = ('type', 'rank', 'priority', 'equalAverage', 'operator',
|
||||
'aboveAverage', 'dxfId', 'stdDev', 'stopIfTrue', 'timePeriod', 'text',
|
||||
'percent', 'bottom')
|
||||
|
||||
|
||||
def __init__(self,
|
||||
type,
|
||||
dxfId=None,
|
||||
priority=0,
|
||||
stopIfTrue=None,
|
||||
aboveAverage=None,
|
||||
percent=None,
|
||||
bottom=None,
|
||||
operator=None,
|
||||
text=None,
|
||||
timePeriod=None,
|
||||
rank=None,
|
||||
stdDev=None,
|
||||
equalAverage=None,
|
||||
formula=(),
|
||||
colorScale=None,
|
||||
dataBar=None,
|
||||
iconSet=None,
|
||||
extLst=None,
|
||||
dxf=None,
|
||||
):
|
||||
self.type = type
|
||||
self.dxfId = dxfId
|
||||
self.priority = priority
|
||||
self.stopIfTrue = stopIfTrue
|
||||
self.aboveAverage = aboveAverage
|
||||
self.percent = percent
|
||||
self.bottom = bottom
|
||||
self.operator = operator
|
||||
self.text = text
|
||||
self.timePeriod = timePeriod
|
||||
self.rank = rank
|
||||
self.stdDev = stdDev
|
||||
self.equalAverage = equalAverage
|
||||
self.formula = formula
|
||||
self.colorScale = colorScale
|
||||
self.dataBar = dataBar
|
||||
self.iconSet = iconSet
|
||||
self.dxf = dxf
|
||||
|
||||
|
||||
def ColorScaleRule(start_type=None,
|
||||
start_value=None,
|
||||
start_color=None,
|
||||
mid_type=None,
|
||||
mid_value=None,
|
||||
mid_color=None,
|
||||
end_type=None,
|
||||
end_value=None,
|
||||
end_color=None):
|
||||
|
||||
"""Backwards compatibility"""
|
||||
formats = []
|
||||
if start_type is not None:
|
||||
formats.append(FormatObject(type=start_type, val=start_value))
|
||||
if mid_type is not None:
|
||||
formats.append(FormatObject(type=mid_type, val=mid_value))
|
||||
if end_type is not None:
|
||||
formats.append(FormatObject(type=end_type, val=end_value))
|
||||
colors = []
|
||||
for v in (start_color, mid_color, end_color):
|
||||
if v is not None:
|
||||
if not isinstance(v, Color):
|
||||
v = Color(v)
|
||||
colors.append(v)
|
||||
cs = ColorScale(cfvo=formats, color=colors)
|
||||
rule = Rule(type="colorScale", colorScale=cs)
|
||||
return rule
|
||||
|
||||
|
||||
def FormulaRule(formula=None, stopIfTrue=None, font=None, border=None,
|
||||
fill=None):
|
||||
"""
|
||||
Conditional formatting with custom differential style
|
||||
"""
|
||||
rule = Rule(type="expression", formula=formula, stopIfTrue=stopIfTrue)
|
||||
rule.dxf = DifferentialStyle(font=font, border=border, fill=fill)
|
||||
return rule
|
||||
|
||||
|
||||
def CellIsRule(operator=None, formula=None, stopIfTrue=None, font=None, border=None, fill=None):
|
||||
"""
|
||||
Conditional formatting rule based on cell contents.
|
||||
"""
|
||||
# Excel doesn't use >, >=, etc, but allow for ease of python development
|
||||
expand = {">": "greaterThan", ">=": "greaterThanOrEqual", "<": "lessThan", "<=": "lessThanOrEqual",
|
||||
"=": "equal", "==": "equal", "!=": "notEqual"}
|
||||
|
||||
operator = expand.get(operator, operator)
|
||||
|
||||
rule = Rule(type='cellIs', operator=operator, formula=formula, stopIfTrue=stopIfTrue)
|
||||
rule.dxf = DifferentialStyle(font=font, border=border, fill=fill)
|
||||
|
||||
return rule
|
||||
|
||||
|
||||
def IconSetRule(icon_style=None, type=None, values=None, showValue=None, percent=None, reverse=None):
|
||||
"""
|
||||
Convenience function for creating icon set rules
|
||||
"""
|
||||
cfvo = []
|
||||
for val in values:
|
||||
cfvo.append(FormatObject(type, val))
|
||||
icon_set = IconSet(iconSet=icon_style, cfvo=cfvo, showValue=showValue,
|
||||
percent=percent, reverse=reverse)
|
||||
rule = Rule(type='iconSet', iconSet=icon_set)
|
||||
|
||||
return rule
|
||||
|
||||
|
||||
def DataBarRule(start_type=None, start_value=None, end_type=None,
|
||||
end_value=None, color=None, showValue=None, minLength=None, maxLength=None):
|
||||
start = FormatObject(start_type, start_value)
|
||||
end = FormatObject(end_type, end_value)
|
||||
data_bar = DataBar(cfvo=[start, end], color=color, showValue=showValue,
|
||||
minLength=minLength, maxLength=maxLength)
|
||||
rule = Rule(type='dataBar', dataBar=data_bar)
|
||||
|
||||
return rule
|
Reference in New Issue
Block a user