projektAI/venv/Lib/site-packages/pandas/io/excel/_xlwt.py
2021-06-06 22:13:05 +02:00

157 lines
4.7 KiB
Python

from typing import TYPE_CHECKING, Dict
import pandas._libs.json as json
from pandas._typing import StorageOptions
from pandas.io.excel._base import ExcelWriter
from pandas.io.excel._util import validate_freeze_panes
if TYPE_CHECKING:
from xlwt import XFStyle
class XlwtWriter(ExcelWriter):
engine = "xlwt"
supported_extensions = (".xls",)
def __init__(
self,
path,
engine=None,
encoding=None,
mode: str = "w",
storage_options: StorageOptions = None,
**engine_kwargs,
):
# Use the xlwt module as the Excel writer.
import xlwt
engine_kwargs["engine"] = engine
if mode == "a":
raise ValueError("Append mode is not supported with xlwt!")
super().__init__(
path, mode=mode, storage_options=storage_options, **engine_kwargs
)
if encoding is None:
encoding = "ascii"
self.book = xlwt.Workbook(encoding=encoding)
self.fm_datetime = xlwt.easyxf(num_format_str=self.datetime_format)
self.fm_date = xlwt.easyxf(num_format_str=self.date_format)
def save(self):
"""
Save workbook to disk.
"""
if self.sheets:
# fails when the ExcelWriter is just opened and then closed
self.book.save(self.handles.handle)
def write_cells(
self, cells, sheet_name=None, startrow=0, startcol=0, freeze_panes=None
):
sheet_name = self._get_sheet_name(sheet_name)
if sheet_name in self.sheets:
wks = self.sheets[sheet_name]
else:
wks = self.book.add_sheet(sheet_name)
self.sheets[sheet_name] = wks
if validate_freeze_panes(freeze_panes):
wks.set_panes_frozen(True)
wks.set_horz_split_pos(freeze_panes[0])
wks.set_vert_split_pos(freeze_panes[1])
style_dict: Dict[str, XFStyle] = {}
for cell in cells:
val, fmt = self._value_with_fmt(cell.val)
stylekey = json.dumps(cell.style)
if fmt:
stylekey += fmt
if stylekey in style_dict:
style = style_dict[stylekey]
else:
style = self._convert_to_style(cell.style, fmt)
style_dict[stylekey] = style
if cell.mergestart is not None and cell.mergeend is not None:
wks.write_merge(
startrow + cell.row,
startrow + cell.mergestart,
startcol + cell.col,
startcol + cell.mergeend,
val,
style,
)
else:
wks.write(startrow + cell.row, startcol + cell.col, val, style)
@classmethod
def _style_to_xlwt(
cls, item, firstlevel: bool = True, field_sep=",", line_sep=";"
) -> str:
"""
helper which recursively generate an xlwt easy style string
for example:
hstyle = {"font": {"bold": True},
"border": {"top": "thin",
"right": "thin",
"bottom": "thin",
"left": "thin"},
"align": {"horiz": "center"}}
will be converted to
font: bold on; \
border: top thin, right thin, bottom thin, left thin; \
align: horiz center;
"""
if hasattr(item, "items"):
if firstlevel:
it = [
f"{key}: {cls._style_to_xlwt(value, False)}"
for key, value in item.items()
]
out = f"{line_sep.join(it)} "
return out
else:
it = [
f"{key} {cls._style_to_xlwt(value, False)}"
for key, value in item.items()
]
out = f"{field_sep.join(it)} "
return out
else:
item = f"{item}"
item = item.replace("True", "on")
item = item.replace("False", "off")
return item
@classmethod
def _convert_to_style(cls, style_dict, num_format_str=None):
"""
converts a style_dict to an xlwt style object
Parameters
----------
style_dict : style dictionary to convert
num_format_str : optional number format string
"""
import xlwt
if style_dict:
xlwt_stylestr = cls._style_to_xlwt(style_dict)
style = xlwt.easyxf(xlwt_stylestr, field_sep=",", line_sep=";")
else:
style = xlwt.XFStyle()
if num_format_str is not None:
style.num_format_str = num_format_str
return style