1###############################################################################
2#
3# ChartColumn - A class for writing the Excel XLSX Column charts.
4#
5# SPDX-License-Identifier: BSD-2-Clause
6# Copyright 2013-2024, John McNamara, jmcnamara@cpan.org
7#
8
9from . import chart
10
11
12class ChartColumn(chart.Chart):
13 """
14 A class for writing the Excel XLSX Column charts.
15
16
17 """
18
19 ###########################################################################
20 #
21 # Public API.
22 #
23 ###########################################################################
24
25 def __init__(self, options=None):
26 """
27 Constructor.
28
29 """
30 super(ChartColumn, self).__init__()
31
32 if options is None:
33 options = {}
34
35 self.subtype = options.get("subtype")
36
37 if not self.subtype:
38 self.subtype = "clustered"
39
40 self.horiz_val_axis = 0
41
42 if self.subtype == "percent_stacked":
43 self.y_axis["defaults"]["num_format"] = "0%"
44
45 # Set the available data label positions for this chart type.
46 self.label_position_default = "outside_end"
47 self.label_positions = {
48 "center": "ctr",
49 "inside_base": "inBase",
50 "inside_end": "inEnd",
51 "outside_end": "outEnd",
52 }
53
54 self.set_y_axis({})
55
56 ###########################################################################
57 #
58 # Private API.
59 #
60 ###########################################################################
61
62 def _write_chart_type(self, args):
63 # Override the virtual superclass method with a chart specific method.
64
65 # Write the c:barChart element.
66 self._write_bar_chart(args)
67
68 def _write_bar_chart(self, args):
69 # Write the <c:barChart> element.
70
71 if args["primary_axes"]:
72 series = self._get_primary_axes_series()
73 else:
74 series = self._get_secondary_axes_series()
75
76 if not len(series):
77 return
78
79 subtype = self.subtype
80 if subtype == "percent_stacked":
81 subtype = "percentStacked"
82
83 # Set a default overlap for stacked charts.
84 if "stacked" in self.subtype and self.series_overlap_1 is None:
85 self.series_overlap_1 = 100
86
87 self._xml_start_tag("c:barChart")
88
89 # Write the c:barDir element.
90 self._write_bar_dir()
91
92 # Write the c:grouping element.
93 self._write_grouping(subtype)
94
95 # Write the c:ser elements.
96 for data in series:
97 self._write_ser(data)
98
99 # Write the c:gapWidth element.
100 if args["primary_axes"]:
101 self._write_gap_width(self.series_gap_1)
102 else:
103 self._write_gap_width(self.series_gap_2)
104
105 # Write the c:overlap element.
106 if args["primary_axes"]:
107 self._write_overlap(self.series_overlap_1)
108 else:
109 self._write_overlap(self.series_overlap_2)
110
111 # Write the c:axId elements
112 self._write_axis_ids(args)
113
114 self._xml_end_tag("c:barChart")
115
116 ###########################################################################
117 #
118 # XML methods.
119 #
120 ###########################################################################
121
122 def _write_bar_dir(self):
123 # Write the <c:barDir> element.
124 val = "col"
125
126 attributes = [("val", val)]
127
128 self._xml_empty_tag("c:barDir", attributes)
129
130 def _write_err_dir(self, val):
131 # Overridden from Chart class since it is not used in Column charts.
132 pass