_writer.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # Copyright (c) 2010-2024 openpyxl
  2. from openpyxl.compat import safe_string
  3. from openpyxl.xml.functions import Element, SubElement, whitespace, XML_NS
  4. from openpyxl import LXML
  5. from openpyxl.utils.datetime import to_excel, to_ISO8601
  6. from datetime import timedelta
  7. from openpyxl.worksheet.formula import DataTableFormula, ArrayFormula
  8. from openpyxl.cell.rich_text import CellRichText
  9. def _set_attributes(cell, styled=None):
  10. """
  11. Set coordinate and datatype
  12. """
  13. coordinate = cell.coordinate
  14. attrs = {'r': coordinate}
  15. if styled:
  16. attrs['s'] = f"{cell.style_id}"
  17. if cell.data_type == "s":
  18. attrs['t'] = "inlineStr"
  19. elif cell.data_type != 'f':
  20. attrs['t'] = cell.data_type
  21. value = cell._value
  22. if cell.data_type == "d":
  23. if hasattr(value, "tzinfo") and value.tzinfo is not None:
  24. raise TypeError("Excel does not support timezones in datetimes. "
  25. "The tzinfo in the datetime/time object must be set to None.")
  26. if cell.parent.parent.iso_dates and not isinstance(value, timedelta):
  27. value = to_ISO8601(value)
  28. else:
  29. attrs['t'] = "n"
  30. value = to_excel(value, cell.parent.parent.epoch)
  31. if cell.hyperlink:
  32. cell.parent._hyperlinks.append(cell.hyperlink)
  33. return value, attrs
  34. def etree_write_cell(xf, worksheet, cell, styled=None):
  35. value, attributes = _set_attributes(cell, styled)
  36. el = Element("c", attributes)
  37. if value is None or value == "":
  38. xf.write(el)
  39. return
  40. if cell.data_type == 'f':
  41. attrib = {}
  42. if isinstance(value, ArrayFormula):
  43. attrib = dict(value)
  44. value = value.text
  45. elif isinstance(value, DataTableFormula):
  46. attrib = dict(value)
  47. value = None
  48. formula = SubElement(el, 'f', attrib)
  49. if value is not None and not attrib.get('t') == "dataTable":
  50. formula.text = value[1:]
  51. value = None
  52. if cell.data_type == 's':
  53. if isinstance(value, CellRichText):
  54. el.append(value.to_tree())
  55. else:
  56. inline_string = Element("is")
  57. text = Element('t')
  58. text.text = value
  59. whitespace(text)
  60. inline_string.append(text)
  61. el.append(inline_string)
  62. else:
  63. cell_content = SubElement(el, 'v')
  64. if value is not None:
  65. cell_content.text = safe_string(value)
  66. xf.write(el)
  67. def lxml_write_cell(xf, worksheet, cell, styled=False):
  68. value, attributes = _set_attributes(cell, styled)
  69. if value == '' or value is None:
  70. with xf.element("c", attributes):
  71. return
  72. with xf.element('c', attributes):
  73. if cell.data_type == 'f':
  74. attrib = {}
  75. if isinstance(value, ArrayFormula):
  76. attrib = dict(value)
  77. value = value.text
  78. elif isinstance(value, DataTableFormula):
  79. attrib = dict(value)
  80. value = None
  81. with xf.element('f', attrib):
  82. if value is not None and not attrib.get('t') == "dataTable":
  83. xf.write(value[1:])
  84. value = None
  85. if cell.data_type == 's':
  86. if isinstance(value, CellRichText):
  87. el = value.to_tree()
  88. xf.write(el)
  89. else:
  90. with xf.element("is"):
  91. if isinstance(value, str):
  92. attrs = {}
  93. if value != value.strip():
  94. attrs["{%s}space" % XML_NS] = "preserve"
  95. el = Element("t", attrs) # lxml can't handle xml-ns
  96. el.text = value
  97. xf.write(el)
  98. else:
  99. with xf.element("v"):
  100. if value is not None:
  101. xf.write(safe_string(value))
  102. if LXML:
  103. write_cell = lxml_write_cell
  104. else:
  105. write_cell = etree_write_cell