formatting.py 2.8 KB

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