formatting.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # Copyright (c) 2010-2024 openpyxl
  2. from collections import OrderedDict
  3. from openpyxl.descriptors import (
  4. Bool,
  5. Sequence,
  6. Alias,
  7. Convertible,
  8. )
  9. from openpyxl.descriptors.serialisable import Serialisable
  10. from .rule import Rule
  11. from openpyxl.worksheet.cell_range import MultiCellRange
  12. class ConditionalFormatting(Serialisable):
  13. tagname = "conditionalFormatting"
  14. sqref = Convertible(expected_type=MultiCellRange)
  15. cells = Alias("sqref")
  16. pivot = Bool(allow_none=True)
  17. cfRule = Sequence(expected_type=Rule)
  18. rules = Alias("cfRule")
  19. def __init__(self, sqref=(), pivot=None, cfRule=(), extLst=None):
  20. self.sqref = sqref
  21. self.pivot = pivot
  22. self.cfRule = cfRule
  23. def __eq__(self, other):
  24. if not isinstance(other, self.__class__):
  25. return False
  26. return self.sqref == other.sqref
  27. def __hash__(self):
  28. return hash(self.sqref)
  29. def __repr__(self):
  30. return "<{cls} {cells}>".format(cls=self.__class__.__name__, cells=self.sqref)
  31. def __contains__(self, coord):
  32. """
  33. Check whether a certain cell is affected by the formatting
  34. """
  35. return coord in self.sqref
  36. class ConditionalFormattingList:
  37. """Conditional formatting rules."""
  38. def __init__(self):
  39. self._cf_rules = OrderedDict()
  40. self.max_priority = 0
  41. def add(self, range_string, cfRule):
  42. """Add a rule such as ColorScaleRule, FormulaRule or CellIsRule
  43. The priority will be added automatically.
  44. """
  45. cf = range_string
  46. if isinstance(range_string, str):
  47. cf = ConditionalFormatting(range_string)
  48. if not isinstance(cfRule, Rule):
  49. raise ValueError("Only instances of openpyxl.formatting.rule.Rule may be added")
  50. rule = cfRule
  51. self.max_priority += 1
  52. if not rule.priority:
  53. rule.priority = self.max_priority
  54. self._cf_rules.setdefault(cf, []).append(rule)
  55. def __bool__(self):
  56. return bool(self._cf_rules)
  57. def __len__(self):
  58. return len(self._cf_rules)
  59. def __iter__(self):
  60. for cf, rules in self._cf_rules.items():
  61. cf.rules = rules
  62. yield cf
  63. def __getitem__(self, key):
  64. """
  65. Get the rules for a cell range
  66. """
  67. if isinstance(key, str):
  68. key = ConditionalFormatting(sqref=key)
  69. return self._cf_rules[key]
  70. def __delitem__(self, key):
  71. key = ConditionalFormatting(sqref=key)
  72. del self._cf_rules[key]
  73. def __setitem__(self, key, rule):
  74. """
  75. Add a rule for a cell range
  76. """
  77. self.add(key, rule)