Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/openpyxl/worksheet/_read_only.py: 23%
112 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1# Copyright (c) 2010-2022 openpyxl
3""" Read worksheets on-demand
4"""
6from .worksheet import Worksheet
7from openpyxl.cell.read_only import ReadOnlyCell, EMPTY_CELL
8from openpyxl.utils import get_column_letter
10from ._reader import WorkSheetParser
13def read_dimension(source):
14 parser = WorkSheetParser(source, [])
15 return parser.parse_dimensions()
18class ReadOnlyWorksheet(object):
20 _min_column = 1
21 _min_row = 1
22 _max_column = _max_row = None
24 # from Standard Worksheet
25 # Methods from Worksheet
26 cell = Worksheet.cell
27 iter_rows = Worksheet.iter_rows
28 values = Worksheet.values
29 rows = Worksheet.rows
30 __getitem__ = Worksheet.__getitem__
31 __iter__ = Worksheet.__iter__
34 def __init__(self, parent_workbook, title, worksheet_path, shared_strings):
35 self.parent = parent_workbook
36 self.title = title
37 self.sheet_state = 'visible'
38 self._current_row = None
39 self._worksheet_path = worksheet_path
40 self._shared_strings = shared_strings
41 self._get_size()
44 def _get_size(self):
45 src = self._get_source()
46 parser = WorkSheetParser(src, [])
47 dimensions = parser.parse_dimensions()
48 src.close()
49 if dimensions is not None:
50 self._min_column, self._min_row, self._max_column, self._max_row = dimensions
53 def _get_source(self):
54 """Parse xml source on demand, must close after use"""
55 return self.parent._archive.open(self._worksheet_path)
58 def _cells_by_row(self, min_col, min_row, max_col, max_row, values_only=False):
59 """
60 The source worksheet file may have columns or rows missing.
61 Missing cells will be created.
62 """
63 filler = EMPTY_CELL
64 if values_only:
65 filler = None
67 max_col = max_col or self.max_column
68 max_row = max_row or self.max_row
69 empty_row = []
70 if max_col is not None:
71 empty_row = (filler,) * (max_col + 1 - min_col)
73 counter = min_row
74 idx = 1
75 src = self._get_source()
76 parser = WorkSheetParser(src, self._shared_strings,
77 data_only=self.parent.data_only, epoch=self.parent.epoch,
78 date_formats=self.parent._date_formats)
79 for idx, row in parser.parse():
80 if max_row is not None and idx > max_row:
81 break
83 # some rows are missing
84 for _ in range(counter, idx):
85 counter += 1
86 yield empty_row
88 # return cells from a row
89 if counter <= idx:
90 row = self._get_row(row, min_col, max_col, values_only)
91 counter += 1
92 yield row
94 src.close() # make sure source is always closed
96 if max_row is not None and max_row < idx:
97 for _ in range(counter, max_row+1):
98 yield empty_row
101 def _get_row(self, row, min_col=1, max_col=None, values_only=False):
102 """
103 Make sure a row contains always the same number of cells or values
104 """
105 if not row and not max_col: # in case someone wants to force rows where there aren't any
106 return ()
108 max_col = max_col or row[-1]['column']
109 row_width = max_col + 1 - min_col
111 new_row = [EMPTY_CELL] * row_width
112 if values_only:
113 new_row = [None] * row_width
115 for cell in row:
116 counter = cell['column']
117 if min_col <= counter <= max_col:
118 idx = counter - min_col # position in list of cells returned
119 new_row[idx] = cell['value']
120 if not values_only:
121 new_row[idx] = ReadOnlyCell(self, **cell)
123 return tuple(new_row)
126 def _get_cell(self, row, column):
127 """Cells are returned by a generator which can be empty"""
128 for row in self._cells_by_row(column, row, column, row):
129 if row:
130 return row[0]
131 return EMPTY_CELL
134 def calculate_dimension(self, force=False):
135 if not all([self.max_column, self.max_row]):
136 if force:
137 self._calculate_dimension()
138 else:
139 raise ValueError("Worksheet is unsized, use calculate_dimension(force=True)")
140 return f"{get_column_letter(self.min_column)}{self.min_row}:{get_column_letter(self.max_column)}{self.max_row}"
143 def _calculate_dimension(self):
144 """
145 Loop through all the cells to get the size of a worksheet.
146 Do this only if it is explicitly requested.
147 """
149 max_col = 0
150 for r in self.rows:
151 if not r:
152 continue
153 cell = r[-1]
154 max_col = max(max_col, cell.column)
156 self._max_row = cell.row
157 self._max_column = max_col
160 def reset_dimensions(self):
161 """
162 Remove worksheet dimensions if these are incorrect in the worksheet source.
163 NB. This probably indicates a bug in the library or application that created
164 the workbook.
165 """
166 self._max_row = self._max_column = None
169 @property
170 def min_row(self):
171 return self._min_row
174 @property
175 def max_row(self):
176 return self._max_row
179 @property
180 def min_column(self):
181 return self._min_column
184 @property
185 def max_column(self):
186 return self._max_column