2024-12-04 13:35:57 +05:00

137 lines
3.9 KiB
Python

# Copyright (c) 2010-2024 openpyxl
from openpyxl.compat import safe_string
from openpyxl.xml.functions import Element, SubElement, whitespace, XML_NS
from openpyxl import LXML
from openpyxl.utils.datetime import to_excel, to_ISO8601
from datetime import timedelta
from openpyxl.worksheet.formula import DataTableFormula, ArrayFormula
from openpyxl.cell.rich_text import CellRichText
def _set_attributes(cell, styled=None):
"""
Set coordinate and datatype
"""
coordinate = cell.coordinate
attrs = {'r': coordinate}
if styled:
attrs['s'] = f"{cell.style_id}"
if cell.data_type == "s":
attrs['t'] = "inlineStr"
elif cell.data_type != 'f':
attrs['t'] = cell.data_type
value = cell._value
if cell.data_type == "d":
if hasattr(value, "tzinfo") and value.tzinfo is not None:
raise TypeError("Excel does not support timezones in datetimes. "
"The tzinfo in the datetime/time object must be set to None.")
if cell.parent.parent.iso_dates and not isinstance(value, timedelta):
value = to_ISO8601(value)
else:
attrs['t'] = "n"
value = to_excel(value, cell.parent.parent.epoch)
if cell.hyperlink:
cell.parent._hyperlinks.append(cell.hyperlink)
return value, attrs
def etree_write_cell(xf, worksheet, cell, styled=None):
value, attributes = _set_attributes(cell, styled)
el = Element("c", attributes)
if value is None or value == "":
xf.write(el)
return
if cell.data_type == 'f':
attrib = {}
if isinstance(value, ArrayFormula):
attrib = dict(value)
value = value.text
elif isinstance(value, DataTableFormula):
attrib = dict(value)
value = None
formula = SubElement(el, 'f', attrib)
if value is not None and not attrib.get('t') == "dataTable":
formula.text = value[1:]
value = None
if cell.data_type == 's':
if isinstance(value, CellRichText):
el.append(value.to_tree())
else:
inline_string = Element("is")
text = Element('t')
text.text = value
whitespace(text)
inline_string.append(text)
el.append(inline_string)
else:
cell_content = SubElement(el, 'v')
if value is not None:
cell_content.text = safe_string(value)
xf.write(el)
def lxml_write_cell(xf, worksheet, cell, styled=False):
value, attributes = _set_attributes(cell, styled)
if value == '' or value is None:
with xf.element("c", attributes):
return
with xf.element('c', attributes):
if cell.data_type == 'f':
attrib = {}
if isinstance(value, ArrayFormula):
attrib = dict(value)
value = value.text
elif isinstance(value, DataTableFormula):
attrib = dict(value)
value = None
with xf.element('f', attrib):
if value is not None and not attrib.get('t') == "dataTable":
xf.write(value[1:])
value = None
if cell.data_type == 's':
if isinstance(value, CellRichText):
el = value.to_tree()
xf.write(el)
else:
with xf.element("is"):
if isinstance(value, str):
attrs = {}
if value != value.strip():
attrs["{%s}space" % XML_NS] = "preserve"
el = Element("t", attrs) # lxml can't handle xml-ns
el.text = value
xf.write(el)
else:
with xf.element("v"):
if value is not None:
xf.write(safe_string(value))
if LXML:
write_cell = lxml_write_cell
else:
write_cell = etree_write_cell