aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/openpyxl/cell/cell.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/cell/cell.py')
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/cell/cell.py332
1 files changed, 332 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/cell/cell.py b/.venv/lib/python3.12/site-packages/openpyxl/cell/cell.py
new file mode 100644
index 00000000..d29be280
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/cell/cell.py
@@ -0,0 +1,332 @@
+# Copyright (c) 2010-2024 openpyxl
+
+"""Manage individual cells in a spreadsheet.
+
+The Cell class is required to know its value and type, display options,
+and any other features of an Excel cell. Utilities for referencing
+cells using Excel's 'A1' column/row nomenclature are also provided.
+
+"""
+
+__docformat__ = "restructuredtext en"
+
+# Python stdlib imports
+from copy import copy
+import datetime
+import re
+
+
+from openpyxl.compat import (
+ NUMERIC_TYPES,
+)
+
+from openpyxl.utils.exceptions import IllegalCharacterError
+
+from openpyxl.utils import get_column_letter
+from openpyxl.styles import numbers, is_date_format
+from openpyxl.styles.styleable import StyleableObject
+from openpyxl.worksheet.hyperlink import Hyperlink
+from openpyxl.worksheet.formula import DataTableFormula, ArrayFormula
+from openpyxl.cell.rich_text import CellRichText
+
+# constants
+
+TIME_TYPES = (datetime.datetime, datetime.date, datetime.time, datetime.timedelta)
+TIME_FORMATS = {
+ datetime.datetime:numbers.FORMAT_DATE_DATETIME,
+ datetime.date:numbers.FORMAT_DATE_YYYYMMDD2,
+ datetime.time:numbers.FORMAT_DATE_TIME6,
+ datetime.timedelta:numbers.FORMAT_DATE_TIMEDELTA,
+ }
+
+STRING_TYPES = (str, bytes, CellRichText)
+KNOWN_TYPES = NUMERIC_TYPES + TIME_TYPES + STRING_TYPES + (bool, type(None))
+
+ILLEGAL_CHARACTERS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')
+ERROR_CODES = ('#NULL!', '#DIV/0!', '#VALUE!', '#REF!', '#NAME?', '#NUM!',
+ '#N/A')
+
+TYPE_STRING = 's'
+TYPE_FORMULA = 'f'
+TYPE_NUMERIC = 'n'
+TYPE_BOOL = 'b'
+TYPE_NULL = 'n'
+TYPE_INLINE = 'inlineStr'
+TYPE_ERROR = 'e'
+TYPE_FORMULA_CACHE_STRING = 'str'
+
+VALID_TYPES = (TYPE_STRING, TYPE_FORMULA, TYPE_NUMERIC, TYPE_BOOL,
+ TYPE_NULL, TYPE_INLINE, TYPE_ERROR, TYPE_FORMULA_CACHE_STRING)
+
+
+_TYPES = {int:'n', float:'n', str:'s', bool:'b'}
+
+
+def get_type(t, value):
+ if isinstance(value, NUMERIC_TYPES):
+ dt = 'n'
+ elif isinstance(value, STRING_TYPES):
+ dt = 's'
+ elif isinstance(value, TIME_TYPES):
+ dt = 'd'
+ elif isinstance(value, (DataTableFormula, ArrayFormula)):
+ dt = 'f'
+ else:
+ return
+ _TYPES[t] = dt
+ return dt
+
+
+def get_time_format(t):
+ value = TIME_FORMATS.get(t)
+ if value:
+ return value
+ for base in t.mro()[1:]:
+ value = TIME_FORMATS.get(base)
+ if value:
+ TIME_FORMATS[t] = value
+ return value
+ raise ValueError("Could not get time format for {0!r}".format(value))
+
+
+class Cell(StyleableObject):
+ """Describes cell associated properties.
+
+ Properties of interest include style, type, value, and address.
+
+ """
+ __slots__ = (
+ 'row',
+ 'column',
+ '_value',
+ 'data_type',
+ 'parent',
+ '_hyperlink',
+ '_comment',
+ )
+
+ def __init__(self, worksheet, row=None, column=None, value=None, style_array=None):
+ super().__init__(worksheet, style_array)
+ self.row = row
+ """Row number of this cell (1-based)"""
+ self.column = column
+ """Column number of this cell (1-based)"""
+ # _value is the stored value, while value is the displayed value
+ self._value = None
+ self._hyperlink = None
+ self.data_type = 'n'
+ if value is not None:
+ self.value = value
+ self._comment = None
+
+
+ @property
+ def coordinate(self):
+ """This cell's coordinate (ex. 'A5')"""
+ col = get_column_letter(self.column)
+ return f"{col}{self.row}"
+
+
+ @property
+ def col_idx(self):
+ """The numerical index of the column"""
+ return self.column
+
+
+ @property
+ def column_letter(self):
+ return get_column_letter(self.column)
+
+
+ @property
+ def encoding(self):
+ return self.parent.encoding
+
+ @property
+ def base_date(self):
+ return self.parent.parent.epoch
+
+
+ def __repr__(self):
+ return "<Cell {0!r}.{1}>".format(self.parent.title, self.coordinate)
+
+ def check_string(self, value):
+ """Check string coding, length, and line break character"""
+ if value is None:
+ return
+ # convert to str string
+ if not isinstance(value, str):
+ value = str(value, self.encoding)
+ value = str(value)
+ # string must never be longer than 32,767 characters
+ # truncate if necessary
+ value = value[:32767]
+ if next(ILLEGAL_CHARACTERS_RE.finditer(value), None):
+ raise IllegalCharacterError(f"{value} cannot be used in worksheets.")
+ return value
+
+ def check_error(self, value):
+ """Tries to convert Error" else N/A"""
+ try:
+ return str(value)
+ except UnicodeDecodeError:
+ return u'#N/A'
+
+
+ def _bind_value(self, value):
+ """Given a value, infer the correct data type"""
+
+ self.data_type = "n"
+ t = type(value)
+ try:
+ dt = _TYPES[t]
+ except KeyError:
+ dt = get_type(t, value)
+
+ if dt is None and value is not None:
+ raise ValueError("Cannot convert {0!r} to Excel".format(value))
+
+ if dt:
+ self.data_type = dt
+
+ if dt == 'd':
+ if not is_date_format(self.number_format):
+ self.number_format = get_time_format(t)
+
+ elif dt == "s" and not isinstance(value, CellRichText):
+ value = self.check_string(value)
+ if len(value) > 1 and value.startswith("="):
+ self.data_type = 'f'
+ elif value in ERROR_CODES:
+ self.data_type = 'e'
+
+ self._value = value
+
+
+ @property
+ def value(self):
+ """Get or set the value held in the cell.
+
+ :type: depends on the value (string, float, int or
+ :class:`datetime.datetime`)
+ """
+ return self._value
+
+ @value.setter
+ def value(self, value):
+ """Set the value and infer type and display options."""
+ self._bind_value(value)
+
+ @property
+ def internal_value(self):
+ """Always returns the value for excel."""
+ return self._value
+
+ @property
+ def hyperlink(self):
+ """Return the hyperlink target or an empty string"""
+ return self._hyperlink
+
+
+ @hyperlink.setter
+ def hyperlink(self, val):
+ """Set value and display for hyperlinks in a cell.
+ Automatically sets the `value` of the cell with link text,
+ but you can modify it afterwards by setting the `value`
+ property, and the hyperlink will remain.
+ Hyperlink is removed if set to ``None``."""
+ if val is None:
+ self._hyperlink = None
+ else:
+ if not isinstance(val, Hyperlink):
+ val = Hyperlink(ref="", target=val)
+ val.ref = self.coordinate
+ self._hyperlink = val
+ if self._value is None:
+ self.value = val.target or val.location
+
+
+ @property
+ def is_date(self):
+ """True if the value is formatted as a date
+
+ :type: bool
+ """
+ return self.data_type == 'd' or (
+ self.data_type == 'n' and is_date_format(self.number_format)
+ )
+
+
+ def offset(self, row=0, column=0):
+ """Returns a cell location relative to this cell.
+
+ :param row: number of rows to offset
+ :type row: int
+
+ :param column: number of columns to offset
+ :type column: int
+
+ :rtype: :class:`openpyxl.cell.Cell`
+ """
+ offset_column = self.col_idx + column
+ offset_row = self.row + row
+ return self.parent.cell(column=offset_column, row=offset_row)
+
+
+ @property
+ def comment(self):
+ """ Returns the comment associated with this cell
+
+ :type: :class:`openpyxl.comments.Comment`
+ """
+ return self._comment
+
+
+ @comment.setter
+ def comment(self, value):
+ """
+ Assign a comment to a cell
+ """
+
+ if value is not None:
+ if value.parent:
+ value = copy(value)
+ value.bind(self)
+ elif value is None and self._comment:
+ self._comment.unbind()
+ self._comment = value
+
+
+class MergedCell(StyleableObject):
+
+ """
+ Describes the properties of a cell in a merged cell and helps to
+ display the borders of the merged cell.
+
+ The value of a MergedCell is always None.
+ """
+
+ __slots__ = ('row', 'column')
+
+ _value = None
+ data_type = "n"
+ comment = None
+ hyperlink = None
+
+
+ def __init__(self, worksheet, row=None, column=None):
+ super().__init__(worksheet)
+ self.row = row
+ self.column = column
+
+
+ def __repr__(self):
+ return "<MergedCell {0!r}.{1}>".format(self.parent.title, self.coordinate)
+
+ coordinate = Cell.coordinate
+ _comment = comment
+ value = _value
+
+
+def WriteOnlyCell(ws=None, value=None):
+ return Cell(worksheet=ws, column=1, row=1, value=value)