Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/xlsxwriter/chart_bar.py: 14%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

69 statements  

1############################################################################### 

2# 

3# ChartBar - A class for writing the Excel XLSX Bar charts. 

4# 

5# SPDX-License-Identifier: BSD-2-Clause 

6# 

7# Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org 

8# 

9 

10from typing import Any, Dict, Optional 

11from warnings import warn 

12 

13from . import chart 

14 

15 

16class ChartBar(chart.Chart): 

17 """ 

18 A class for writing the Excel XLSX Bar charts. 

19 

20 

21 """ 

22 

23 ########################################################################### 

24 # 

25 # Public API. 

26 # 

27 ########################################################################### 

28 

29 def __init__(self, options: Optional[Dict[str, Any]] = None) -> None: 

30 """ 

31 Constructor. 

32 

33 """ 

34 super().__init__() 

35 

36 if options is None: 

37 options = {} 

38 

39 self.subtype = options.get("subtype") 

40 

41 if not self.subtype: 

42 self.subtype = "clustered" 

43 

44 self.cat_axis_position = "l" 

45 self.val_axis_position = "b" 

46 self.horiz_val_axis = 0 

47 self.horiz_cat_axis = 1 

48 self.show_crosses = False 

49 

50 # Override and reset the default axis values. 

51 self.x_axis["defaults"]["major_gridlines"] = {"visible": 1} 

52 self.y_axis["defaults"]["major_gridlines"] = {"visible": 0} 

53 

54 if self.subtype == "percent_stacked": 

55 self.x_axis["defaults"]["num_format"] = "0%" 

56 

57 # Set the available data label positions for this chart type. 

58 self.label_position_default = "outside_end" 

59 self.label_positions = { 

60 "center": "ctr", 

61 "inside_base": "inBase", 

62 "inside_end": "inEnd", 

63 "outside_end": "outEnd", 

64 } 

65 

66 self.set_x_axis({}) 

67 self.set_y_axis({}) 

68 

69 def combine(self, chart: Optional[chart.Chart] = None) -> None: 

70 # pylint: disable=redefined-outer-name 

71 """ 

72 Create a combination chart with a secondary chart. 

73 

74 Note: Override parent method to add an extra check that is required 

75 for Bar charts to ensure that their combined chart is on a secondary 

76 axis. 

77 

78 Args: 

79 chart: The secondary chart to combine with the primary chart. 

80 

81 Returns: 

82 Nothing. 

83 

84 """ 

85 if chart is None: 

86 return 

87 

88 if not chart.is_secondary: 

89 warn("Charts combined with Bar charts must be on a secondary axis") 

90 

91 self.combined = chart 

92 

93 ########################################################################### 

94 # 

95 # Private API. 

96 # 

97 ########################################################################### 

98 

99 def _write_chart_type(self, args) -> None: 

100 # Override the virtual superclass method with a chart specific method. 

101 if args["primary_axes"]: 

102 # Reverse X and Y axes for Bar charts. 

103 tmp = self.y_axis 

104 self.y_axis = self.x_axis 

105 self.x_axis = tmp 

106 

107 if self.y2_axis["position"] == "r": 

108 self.y2_axis["position"] = "t" 

109 

110 # Write the c:barChart element. 

111 self._write_bar_chart(args) 

112 

113 def _write_bar_chart(self, args) -> None: 

114 # Write the <c:barChart> element. 

115 

116 if args["primary_axes"]: 

117 series = self._get_primary_axes_series() 

118 else: 

119 series = self._get_secondary_axes_series() 

120 

121 if not series: 

122 return 

123 

124 subtype = self.subtype 

125 if subtype == "percent_stacked": 

126 subtype = "percentStacked" 

127 

128 # Set a default overlap for stacked charts. 

129 if "stacked" in self.subtype and self.series_overlap_1 is None: 

130 self.series_overlap_1 = 100 

131 

132 self._xml_start_tag("c:barChart") 

133 

134 # Write the c:barDir element. 

135 self._write_bar_dir() 

136 

137 # Write the c:grouping element. 

138 self._write_grouping(subtype) 

139 

140 # Write the c:ser elements. 

141 for data in series: 

142 self._write_ser(data) 

143 

144 # Write the c:gapWidth element. 

145 if args["primary_axes"]: 

146 self._write_gap_width(self.series_gap_1) 

147 else: 

148 self._write_gap_width(self.series_gap_2) 

149 

150 # Write the c:overlap element. 

151 if args["primary_axes"]: 

152 self._write_overlap(self.series_overlap_1) 

153 else: 

154 self._write_overlap(self.series_overlap_2) 

155 

156 # Write the c:axId elements 

157 self._write_axis_ids(args) 

158 

159 self._xml_end_tag("c:barChart") 

160 

161 ########################################################################### 

162 # 

163 # XML methods. 

164 # 

165 ########################################################################### 

166 

167 def _write_bar_dir(self) -> None: 

168 # Write the <c:barDir> element. 

169 val = "bar" 

170 

171 attributes = [("val", val)] 

172 

173 self._xml_empty_tag("c:barDir", attributes) 

174 

175 def _write_err_dir(self, val) -> None: 

176 # Overridden from Chart class since it is not used in Bar charts. 

177 pass