borders.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. # Copyright (c) 2010-2024 openpyxl
  2. from openpyxl.compat import safe_string
  3. from openpyxl.descriptors import (
  4. NoneSet,
  5. Typed,
  6. Bool,
  7. Alias,
  8. Sequence,
  9. Integer,
  10. )
  11. from openpyxl.descriptors.serialisable import Serialisable
  12. from .colors import ColorDescriptor
  13. BORDER_NONE = None
  14. BORDER_DASHDOT = 'dashDot'
  15. BORDER_DASHDOTDOT = 'dashDotDot'
  16. BORDER_DASHED = 'dashed'
  17. BORDER_DOTTED = 'dotted'
  18. BORDER_DOUBLE = 'double'
  19. BORDER_HAIR = 'hair'
  20. BORDER_MEDIUM = 'medium'
  21. BORDER_MEDIUMDASHDOT = 'mediumDashDot'
  22. BORDER_MEDIUMDASHDOTDOT = 'mediumDashDotDot'
  23. BORDER_MEDIUMDASHED = 'mediumDashed'
  24. BORDER_SLANTDASHDOT = 'slantDashDot'
  25. BORDER_THICK = 'thick'
  26. BORDER_THIN = 'thin'
  27. class Side(Serialisable):
  28. """Border options for use in styles.
  29. Caution: if you do not specify a border_style, other attributes will
  30. have no effect !"""
  31. color = ColorDescriptor(allow_none=True)
  32. style = NoneSet(values=('dashDot','dashDotDot', 'dashed','dotted',
  33. 'double','hair', 'medium', 'mediumDashDot', 'mediumDashDotDot',
  34. 'mediumDashed', 'slantDashDot', 'thick', 'thin')
  35. )
  36. border_style = Alias('style')
  37. def __init__(self, style=None, color=None, border_style=None):
  38. if border_style is not None:
  39. style = border_style
  40. self.style = style
  41. self.color = color
  42. class Border(Serialisable):
  43. """Border positioning for use in styles."""
  44. tagname = "border"
  45. __elements__ = ('start', 'end', 'left', 'right', 'top', 'bottom',
  46. 'diagonal', 'vertical', 'horizontal')
  47. # child elements
  48. start = Typed(expected_type=Side, allow_none=True)
  49. end = Typed(expected_type=Side, allow_none=True)
  50. left = Typed(expected_type=Side, allow_none=True)
  51. right = Typed(expected_type=Side, allow_none=True)
  52. top = Typed(expected_type=Side, allow_none=True)
  53. bottom = Typed(expected_type=Side, allow_none=True)
  54. diagonal = Typed(expected_type=Side, allow_none=True)
  55. vertical = Typed(expected_type=Side, allow_none=True)
  56. horizontal = Typed(expected_type=Side, allow_none=True)
  57. # attributes
  58. outline = Bool()
  59. diagonalUp = Bool()
  60. diagonalDown = Bool()
  61. def __init__(self, left=None, right=None, top=None,
  62. bottom=None, diagonal=None, diagonal_direction=None,
  63. vertical=None, horizontal=None, diagonalUp=False, diagonalDown=False,
  64. outline=True, start=None, end=None):
  65. self.left = left
  66. self.right = right
  67. self.top = top
  68. self.bottom = bottom
  69. self.diagonal = diagonal
  70. self.vertical = vertical
  71. self.horizontal = horizontal
  72. self.diagonal_direction = diagonal_direction
  73. self.diagonalUp = diagonalUp
  74. self.diagonalDown = diagonalDown
  75. self.outline = outline
  76. self.start = start
  77. self.end = end
  78. def __iter__(self):
  79. for attr in self.__attrs__:
  80. value = getattr(self, attr)
  81. if value and attr != "outline":
  82. yield attr, safe_string(value)
  83. elif attr == "outline" and not value:
  84. yield attr, safe_string(value)
  85. DEFAULT_BORDER = Border(left=Side(), right=Side(), top=Side(), bottom=Side(), diagonal=Side())