Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/pandas/io/excel/_xlwt.py: 23%

92 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1from __future__ import annotations 

2 

3from typing import ( 

4 TYPE_CHECKING, 

5 Any, 

6 Tuple, 

7 cast, 

8) 

9 

10import pandas._libs.json as json 

11from pandas._typing import ( 

12 FilePath, 

13 StorageOptions, 

14 WriteExcelBuffer, 

15) 

16 

17from pandas.io.excel._base import ExcelWriter 

18from pandas.io.excel._util import ( 

19 combine_kwargs, 

20 validate_freeze_panes, 

21) 

22 

23if TYPE_CHECKING: 23 ↛ 24line 23 didn't jump to line 24, because the condition on line 23 was never true

24 from xlwt import ( 

25 Workbook, 

26 XFStyle, 

27 ) 

28 

29 

30class XlwtWriter(ExcelWriter): 

31 _engine = "xlwt" 

32 _supported_extensions = (".xls",) 

33 

34 def __init__( 

35 self, 

36 path: FilePath | WriteExcelBuffer | ExcelWriter, 

37 engine: str | None = None, 

38 date_format: str | None = None, 

39 datetime_format: str | None = None, 

40 encoding: str | None = None, 

41 mode: str = "w", 

42 storage_options: StorageOptions = None, 

43 if_sheet_exists: str | None = None, 

44 engine_kwargs: dict[str, Any] | None = None, 

45 **kwargs, 

46 ) -> None: 

47 # Use the xlwt module as the Excel writer. 

48 import xlwt 

49 

50 engine_kwargs = combine_kwargs(engine_kwargs, kwargs) 

51 

52 if mode == "a": 

53 raise ValueError("Append mode is not supported with xlwt!") 

54 

55 super().__init__( 

56 path, 

57 mode=mode, 

58 storage_options=storage_options, 

59 if_sheet_exists=if_sheet_exists, 

60 engine_kwargs=engine_kwargs, 

61 ) 

62 

63 if encoding is None: 

64 encoding = "ascii" 

65 self._book = xlwt.Workbook(encoding=encoding, **engine_kwargs) 

66 self._fm_datetime = xlwt.easyxf(num_format_str=self._datetime_format) 

67 self._fm_date = xlwt.easyxf(num_format_str=self._date_format) 

68 

69 @property 

70 def book(self) -> Workbook: 

71 """ 

72 Book instance of class xlwt.Workbook. 

73 

74 This attribute can be used to access engine-specific features. 

75 """ 

76 return self._book 

77 

78 @book.setter 

79 def book(self, other: Workbook) -> None: 

80 """ 

81 Set book instance. Class type will depend on the engine used. 

82 """ 

83 self._deprecate_set_book() 

84 self._book = other 

85 

86 @property 

87 def sheets(self) -> dict[str, Any]: 

88 """Mapping of sheet names to sheet objects.""" 

89 result = {sheet.name: sheet for sheet in self.book._Workbook__worksheets} 

90 return result 

91 

92 @property 

93 def fm_date(self): 

94 """ 

95 XFStyle formatter for dates. 

96 """ 

97 self._deprecate("fm_date") 

98 return self._fm_date 

99 

100 @property 

101 def fm_datetime(self): 

102 """ 

103 XFStyle formatter for dates. 

104 """ 

105 self._deprecate("fm_datetime") 

106 return self._fm_datetime 

107 

108 def _save(self) -> None: 

109 """ 

110 Save workbook to disk. 

111 """ 

112 if self.sheets: 

113 # fails when the ExcelWriter is just opened and then closed 

114 self.book.save(self._handles.handle) 

115 

116 def _write_cells( 

117 self, 

118 cells, 

119 sheet_name: str | None = None, 

120 startrow: int = 0, 

121 startcol: int = 0, 

122 freeze_panes: tuple[int, int] | None = None, 

123 ) -> None: 

124 

125 sheet_name = self._get_sheet_name(sheet_name) 

126 

127 if sheet_name in self.sheets: 

128 wks = self.sheets[sheet_name] 

129 else: 

130 wks = self.book.add_sheet(sheet_name) 

131 self.sheets[sheet_name] = wks 

132 

133 if validate_freeze_panes(freeze_panes): 

134 freeze_panes = cast(Tuple[int, int], freeze_panes) 

135 wks.set_panes_frozen(True) 

136 wks.set_horz_split_pos(freeze_panes[0]) 

137 wks.set_vert_split_pos(freeze_panes[1]) 

138 

139 style_dict: dict[str, XFStyle] = {} 

140 

141 for cell in cells: 

142 val, fmt = self._value_with_fmt(cell.val) 

143 

144 stylekey = json.dumps(cell.style) 

145 if fmt: 

146 stylekey += fmt 

147 

148 if stylekey in style_dict: 

149 style = style_dict[stylekey] 

150 else: 

151 style = self._convert_to_style(cell.style, fmt) 

152 style_dict[stylekey] = style 

153 

154 if cell.mergestart is not None and cell.mergeend is not None: 

155 wks.write_merge( 

156 startrow + cell.row, 

157 startrow + cell.mergestart, 

158 startcol + cell.col, 

159 startcol + cell.mergeend, 

160 val, 

161 style, 

162 ) 

163 else: 

164 wks.write(startrow + cell.row, startcol + cell.col, val, style) 

165 

166 @classmethod 

167 def _style_to_xlwt( 

168 cls, item, firstlevel: bool = True, field_sep: str = ",", line_sep: str = ";" 

169 ) -> str: 

170 """ 

171 helper which recursively generate an xlwt easy style string 

172 for example: 

173 

174 hstyle = {"font": {"bold": True}, 

175 "border": {"top": "thin", 

176 "right": "thin", 

177 "bottom": "thin", 

178 "left": "thin"}, 

179 "align": {"horiz": "center"}} 

180 will be converted to 

181 font: bold on; \ 

182 border: top thin, right thin, bottom thin, left thin; \ 

183 align: horiz center; 

184 """ 

185 if hasattr(item, "items"): 

186 if firstlevel: 

187 it = [ 

188 f"{key}: {cls._style_to_xlwt(value, False)}" 

189 for key, value in item.items() 

190 ] 

191 out = f"{line_sep.join(it)} " 

192 return out 

193 else: 

194 it = [ 

195 f"{key} {cls._style_to_xlwt(value, False)}" 

196 for key, value in item.items() 

197 ] 

198 out = f"{field_sep.join(it)} " 

199 return out 

200 else: 

201 item = f"{item}" 

202 item = item.replace("True", "on") 

203 item = item.replace("False", "off") 

204 return item 

205 

206 @classmethod 

207 def _convert_to_style( 

208 cls, style_dict, num_format_str: str | None = None 

209 ) -> XFStyle: 

210 """ 

211 converts a style_dict to an xlwt style object 

212 

213 Parameters 

214 ---------- 

215 style_dict : style dictionary to convert 

216 num_format_str : optional number format string 

217 """ 

218 import xlwt 

219 

220 if style_dict: 

221 xlwt_stylestr = cls._style_to_xlwt(style_dict) 

222 style = xlwt.easyxf(xlwt_stylestr, field_sep=",", line_sep=";") 

223 else: 

224 style = xlwt.XFStyle() 

225 if num_format_str is not None: 

226 style.num_format_str = num_format_str 

227 

228 return style