hyb
2026-01-09 4cb426cb3ae31e772a09d4ade5b2f0242aaeefa0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# 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