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
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1from __future__ import annotations
3from typing import (
4 TYPE_CHECKING,
5 Any,
6 Tuple,
7 cast,
8)
10import pandas._libs.json as json
11from pandas._typing import (
12 FilePath,
13 StorageOptions,
14 WriteExcelBuffer,
15)
17from pandas.io.excel._base import ExcelWriter
18from pandas.io.excel._util import (
19 combine_kwargs,
20 validate_freeze_panes,
21)
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 )
30class XlwtWriter(ExcelWriter):
31 _engine = "xlwt"
32 _supported_extensions = (".xls",)
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
50 engine_kwargs = combine_kwargs(engine_kwargs, kwargs)
52 if mode == "a":
53 raise ValueError("Append mode is not supported with xlwt!")
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 )
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)
69 @property
70 def book(self) -> Workbook:
71 """
72 Book instance of class xlwt.Workbook.
74 This attribute can be used to access engine-specific features.
75 """
76 return self._book
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
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
92 @property
93 def fm_date(self):
94 """
95 XFStyle formatter for dates.
96 """
97 self._deprecate("fm_date")
98 return self._fm_date
100 @property
101 def fm_datetime(self):
102 """
103 XFStyle formatter for dates.
104 """
105 self._deprecate("fm_datetime")
106 return self._fm_datetime
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)
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:
125 sheet_name = self._get_sheet_name(sheet_name)
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
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])
139 style_dict: dict[str, XFStyle] = {}
141 for cell in cells:
142 val, fmt = self._value_with_fmt(cell.val)
144 stylekey = json.dumps(cell.style)
145 if fmt:
146 stylekey += fmt
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
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)
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:
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
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
213 Parameters
214 ----------
215 style_dict : style dictionary to convert
216 num_format_str : optional number format string
217 """
218 import xlwt
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
228 return style