about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/openpyxl/worksheet/_read_only.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/worksheet/_read_only.py')
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/worksheet/_read_only.py190
1 files changed, 190 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/worksheet/_read_only.py b/.venv/lib/python3.12/site-packages/openpyxl/worksheet/_read_only.py
new file mode 100644
index 00000000..95852f21
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/worksheet/_read_only.py
@@ -0,0 +1,190 @@
+# Copyright (c) 2010-2024 openpyxl
+
+""" Read worksheets on-demand
+"""
+
+from .worksheet import Worksheet
+from openpyxl.cell.read_only import ReadOnlyCell, EMPTY_CELL
+from openpyxl.utils import get_column_letter
+
+from ._reader import WorkSheetParser
+from openpyxl.workbook.defined_name import DefinedNameDict
+
+
+def read_dimension(source):
+    parser = WorkSheetParser(source, [])
+    return parser.parse_dimensions()
+
+
+class ReadOnlyWorksheet:
+
+    _min_column = 1
+    _min_row = 1
+    _max_column = _max_row = None
+
+    # from Standard Worksheet
+    # Methods from Worksheet
+    cell = Worksheet.cell
+    iter_rows = Worksheet.iter_rows
+    values = Worksheet.values
+    rows = Worksheet.rows
+    __getitem__ = Worksheet.__getitem__
+    __iter__ = Worksheet.__iter__
+
+
+    def __init__(self, parent_workbook, title, worksheet_path, shared_strings):
+        self.parent = parent_workbook
+        self.title = title
+        self.sheet_state = 'visible'
+        self._current_row = None
+        self._worksheet_path = worksheet_path
+        self._shared_strings = shared_strings
+        self._get_size()
+        self.defined_names = DefinedNameDict()
+
+
+    def _get_size(self):
+        src = self._get_source()
+        parser = WorkSheetParser(src, [])
+        dimensions = parser.parse_dimensions()
+        src.close()
+        if dimensions is not None:
+            self._min_column, self._min_row, self._max_column, self._max_row = dimensions
+
+
+    def _get_source(self):
+        """Parse xml source on demand, must close after use"""
+        return self.parent._archive.open(self._worksheet_path)
+
+
+    def _cells_by_row(self, min_col, min_row, max_col, max_row, values_only=False):
+        """
+        The source worksheet file may have columns or rows missing.
+        Missing cells will be created.
+        """
+        filler = EMPTY_CELL
+        if values_only:
+            filler = None
+
+        max_col = max_col or self.max_column
+        max_row = max_row or self.max_row
+        empty_row = []
+        if max_col is not None:
+            empty_row = (filler,) * (max_col + 1 - min_col)
+
+        counter = min_row
+        idx = 1
+        with self._get_source() as src:
+            parser = WorkSheetParser(src,
+                                     self._shared_strings,
+                                     data_only=self.parent.data_only,
+                                     epoch=self.parent.epoch,
+                                     date_formats=self.parent._date_formats,
+                                     timedelta_formats=self.parent._timedelta_formats)
+
+            for idx, row in parser.parse():
+                if max_row is not None and idx > max_row:
+                    break
+
+                # some rows are missing
+                for _ in range(counter, idx):
+                    counter += 1
+                    yield empty_row
+
+                # return cells from a row
+                if counter <= idx:
+                    row = self._get_row(row, min_col, max_col, values_only)
+                    counter += 1
+                    yield row
+
+        if max_row is not None and max_row < idx:
+            for _ in range(counter, max_row+1):
+                yield empty_row
+
+
+    def _get_row(self, row, min_col=1, max_col=None, values_only=False):
+        """
+        Make sure a row contains always the same number of cells or values
+        """
+        if not row and not max_col: # in case someone wants to force rows where there aren't any
+            return ()
+
+        max_col = max_col or  row[-1]['column']
+        row_width = max_col + 1 - min_col
+
+        new_row = [EMPTY_CELL] * row_width
+        if values_only:
+            new_row = [None] * row_width
+
+        for cell in row:
+            counter = cell['column']
+            if min_col <= counter <= max_col:
+                idx = counter - min_col # position in list of cells returned
+                new_row[idx] = cell['value']
+                if not values_only:
+                    new_row[idx] = ReadOnlyCell(self, **cell)
+
+        return tuple(new_row)
+
+
+    def _get_cell(self, row, column):
+        """Cells are returned by a generator which can be empty"""
+        for row in self._cells_by_row(column, row, column, row):
+            if row:
+                return row[0]
+        return EMPTY_CELL
+
+
+    def calculate_dimension(self, force=False):
+        if not all([self.max_column, self.max_row]):
+            if force:
+                self._calculate_dimension()
+            else:
+                raise ValueError("Worksheet is unsized, use calculate_dimension(force=True)")
+        return f"{get_column_letter(self.min_column)}{self.min_row}:{get_column_letter(self.max_column)}{self.max_row}"
+
+
+    def _calculate_dimension(self):
+        """
+        Loop through all the cells to get the size of a worksheet.
+        Do this only if it is explicitly requested.
+        """
+
+        max_col = 0
+        for r in self.rows:
+            if not r:
+                continue
+            cell = r[-1]
+            max_col = max(max_col, cell.column)
+
+        self._max_row = cell.row
+        self._max_column = max_col
+
+
+    def reset_dimensions(self):
+        """
+        Remove worksheet dimensions if these are incorrect in the worksheet source.
+        NB. This probably indicates a bug in the library or application that created
+        the workbook.
+        """
+        self._max_row = self._max_column = None
+
+
+    @property
+    def min_row(self):
+        return self._min_row
+
+
+    @property
+    def max_row(self):
+        return self._max_row
+
+
+    @property
+    def min_column(self):
+        return self._min_column
+
+
+    @property
+    def max_column(self):
+        return self._max_column