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