PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/Windows/Python3.8/WPy64-3830/WPy64-3830/python-3.8.3.amd64/Lib/site-packages/openpyxl/cell/cell.py

https://gitlab.com/abhi1tb/build
Python | 330 lines | 321 code | 2 blank | 7 comment | 1 complexity | f7db29c9c483f9b30022d2c2babb566e MD5 | raw file
  1. # Copyright (c) 2010-2019 openpyxl
  2. """Manage individual cells in a spreadsheet.
  3. The Cell class is required to know its value and type, display options,
  4. and any other features of an Excel cell. Utilities for referencing
  5. cells using Excel's 'A1' column/row nomenclature are also provided.
  6. """
  7. __docformat__ = "restructuredtext en"
  8. # Python stdlib imports
  9. from copy import copy
  10. import datetime
  11. import re
  12. from openpyxl.compat import (
  13. NUMERIC_TYPES,
  14. deprecated,
  15. )
  16. from openpyxl.utils.exceptions import IllegalCharacterError
  17. from openpyxl.utils import get_column_letter
  18. from openpyxl.styles import numbers, is_date_format
  19. from openpyxl.styles.styleable import StyleableObject
  20. from openpyxl.worksheet.hyperlink import Hyperlink
  21. # constants
  22. TIME_TYPES = (datetime.datetime, datetime.date, datetime.time, datetime.timedelta)
  23. TIME_FORMATS = {
  24. datetime.datetime:numbers.FORMAT_DATE_DATETIME,
  25. datetime.date:numbers.FORMAT_DATE_YYYYMMDD2,
  26. datetime.time:numbers.FORMAT_DATE_TIME6,
  27. datetime.timedelta:numbers.FORMAT_DATE_TIMEDELTA,
  28. }
  29. try:
  30. from pandas import Timestamp
  31. TIME_TYPES = TIME_TYPES + (Timestamp,)
  32. TIME_FORMATS[Timestamp] = numbers.FORMAT_DATE_DATETIME
  33. except ImportError:
  34. pass
  35. STRING_TYPES = (str, bytes)
  36. KNOWN_TYPES = NUMERIC_TYPES + TIME_TYPES + STRING_TYPES + (bool, type(None))
  37. ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')
  38. ERROR_CODES = ('#NULL!', '#DIV/0!', '#VALUE!', '#REF!', '#NAME?', '#NUM!',
  39. '#N/A')
  40. ERROR_CODES = ERROR_CODES
  41. TYPE_STRING = 's'
  42. TYPE_FORMULA = 'f'
  43. TYPE_NUMERIC = 'n'
  44. TYPE_BOOL = 'b'
  45. TYPE_NULL = 'n'
  46. TYPE_INLINE = 'inlineStr'
  47. TYPE_ERROR = 'e'
  48. TYPE_FORMULA_CACHE_STRING = 'str'
  49. VALID_TYPES = (TYPE_STRING, TYPE_FORMULA, TYPE_NUMERIC, TYPE_BOOL,
  50. TYPE_NULL, TYPE_INLINE, TYPE_ERROR, TYPE_FORMULA_CACHE_STRING)
  51. _TYPES = {int:'n', float:'n', str:'s', bool:'b'}
  52. def get_type(t, value):
  53. if isinstance(value, NUMERIC_TYPES):
  54. dt = 'n'
  55. elif isinstance(value, STRING_TYPES):
  56. dt = 's'
  57. elif isinstance(value, TIME_TYPES):
  58. dt = 'd'
  59. else:
  60. return
  61. _TYPES[t] = dt
  62. return dt
  63. class Cell(StyleableObject):
  64. """Describes cell associated properties.
  65. Properties of interest include style, type, value, and address.
  66. """
  67. __slots__ = (
  68. 'row',
  69. 'column',
  70. '_value',
  71. 'data_type',
  72. 'parent',
  73. '_hyperlink',
  74. '_comment',
  75. )
  76. def __init__(self, worksheet, row=None, column=None, value=None, style_array=None):
  77. super(Cell, self).__init__(worksheet, style_array)
  78. self.row = row
  79. """Row number of this cell (1-based)"""
  80. self.column = column
  81. """Column number of this cell (1-based)"""
  82. # _value is the stored value, while value is the displayed value
  83. self._value = None
  84. self._hyperlink = None
  85. self.data_type = 'n'
  86. if value is not None:
  87. self.value = value
  88. self._comment = None
  89. @property
  90. def coordinate(self):
  91. """This cell's coordinate (ex. 'A5')"""
  92. col = get_column_letter(self.column)
  93. return f"{col}{self.row}"
  94. @property
  95. def col_idx(self):
  96. """The numerical index of the column"""
  97. return self.column
  98. @property
  99. def column_letter(self):
  100. return get_column_letter(self.column)
  101. @property
  102. def encoding(self):
  103. return self.parent.encoding
  104. @property
  105. def base_date(self):
  106. return self.parent.parent.epoch
  107. def __repr__(self):
  108. return "<Cell {0!r}.{1}>".format(self.parent.title, self.coordinate)
  109. def check_string(self, value):
  110. """Check string coding, length, and line break character"""
  111. if value is None:
  112. return
  113. # convert to str string
  114. if not isinstance(value, str):
  115. value = str(value, self.encoding)
  116. value = str(value)
  117. # string must never be longer than 32,767 characters
  118. # truncate if necessary
  119. value = value[:32767]
  120. if next(ILLEGAL_CHARACTERS_RE.finditer(value), None):
  121. raise IllegalCharacterError
  122. return value
  123. def check_error(self, value):
  124. """Tries to convert Error" else N/A"""
  125. try:
  126. return str(value)
  127. except UnicodeDecodeError:
  128. return u'#N/A'
  129. def _bind_value(self, value):
  130. """Given a value, infer the correct data type"""
  131. self.data_type = "n"
  132. t = type(value)
  133. try:
  134. dt = _TYPES[t]
  135. except KeyError:
  136. dt = get_type(t, value)
  137. if dt is not None:
  138. self.data_type = dt
  139. if dt == 'n' or dt == 'b':
  140. pass
  141. elif dt == 'd':
  142. if not is_date_format(self.number_format):
  143. self.number_format = TIME_FORMATS[t]
  144. self.data_type = "d"
  145. elif dt == "s":
  146. value = self.check_string(value)
  147. if len(value) > 1 and value.startswith("="):
  148. self.data_type = 'f'
  149. elif value in ERROR_CODES:
  150. self.data_type = 'e'
  151. elif value is not None:
  152. raise ValueError("Cannot convert {0!r} to Excel".format(value))
  153. self._value = value
  154. @property
  155. def value(self):
  156. """Get or set the value held in the cell.
  157. :type: depends on the value (string, float, int or
  158. :class:`datetime.datetime`)
  159. """
  160. return self._value
  161. @value.setter
  162. def value(self, value):
  163. """Set the value and infer type and display options."""
  164. self._bind_value(value)
  165. @property
  166. def internal_value(self):
  167. """Always returns the value for excel."""
  168. return self._value
  169. @property
  170. def hyperlink(self):
  171. """Return the hyperlink target or an empty string"""
  172. return self._hyperlink
  173. @hyperlink.setter
  174. def hyperlink(self, val):
  175. """Set value and display for hyperlinks in a cell.
  176. Automatically sets the `value` of the cell with link text,
  177. but you can modify it afterwards by setting the `value`
  178. property, and the hyperlink will remain.
  179. Hyperlink is removed if set to ``None``."""
  180. if val is None:
  181. self._hyperlink = None
  182. else:
  183. if not isinstance(val, Hyperlink):
  184. val = Hyperlink(ref="", target=val)
  185. val.ref = self.coordinate
  186. self._hyperlink = val
  187. if self._value is None:
  188. self.value = val.target or val.location
  189. @property
  190. def is_date(self):
  191. """True if the value is formatted as a date
  192. :type: bool
  193. """
  194. return self.data_type == 'd' or (
  195. self.data_type == 'n' and is_date_format(self.number_format)
  196. )
  197. def offset(self, row=0, column=0):
  198. """Returns a cell location relative to this cell.
  199. :param row: number of rows to offset
  200. :type row: int
  201. :param column: number of columns to offset
  202. :type column: int
  203. :rtype: :class:`openpyxl.cell.Cell`
  204. """
  205. offset_column = self.col_idx + column
  206. offset_row = self.row + row
  207. return self.parent.cell(column=offset_column, row=offset_row)
  208. @property
  209. def comment(self):
  210. """ Returns the comment associated with this cell
  211. :type: :class:`openpyxl.comments.Comment`
  212. """
  213. return self._comment
  214. @comment.setter
  215. def comment(self, value):
  216. """
  217. Assign a comment to a cell
  218. """
  219. if value is not None:
  220. if value.parent:
  221. value = copy(value)
  222. value.bind(self)
  223. elif value is None and self._comment:
  224. self._comment.unbind()
  225. self._comment = value
  226. class MergedCell(StyleableObject):
  227. """
  228. Describes the properties of a cell in a merged cell and helps to
  229. display the borders of the merged cell.
  230. The value of a MergedCell is always None.
  231. """
  232. __slots__ = ('row', 'column')
  233. _value = None
  234. data_type = "n"
  235. comment = None
  236. hyperlink = None
  237. def __init__(self, worksheet, row=None, column=None):
  238. super(MergedCell, self).__init__(worksheet)
  239. self.row = row
  240. self.column = column
  241. def __repr__(self):
  242. return "<MergedCell {0!r}.{1}>".format(self.parent.title, self.coordinate)
  243. coordinate = Cell.coordinate
  244. _comment = comment
  245. value = _value
  246. def WriteOnlyCell(ws=None, value=None):
  247. return Cell(worksheet=ws, column=1, row=1, value=value)