def _get_update_chunks(self, start, end, vals): start = get_cell_as_tuple(start) end = get_cell_as_tuple(end) num_cols = end[COL] - start[COL] + 1 num_rows = end[ROW] - start[ROW] + 1 num_cells = num_cols * num_rows if num_cells != len(vals): raise MissMatchException( "Number of values needs to match number of cells") chunk_rows = self._max_range_chunk_size // num_cols chunk_size = chunk_rows * num_cols end_cell = (start[ROW] - 1, 0) for val_chunks in chunks(vals, int(chunk_size)): start_cell = (end_cell[ROW] + 1, start[COL]) end_cell = ( min(start_cell[ROW] + chunk_rows - 1, start[ROW] + num_rows - 1), end[COL], ) yield start_cell, end_cell, val_chunks
def update_cells(self, start, end, vals, sheet=None): """ Update the values in a given range. The values should be listed in order from left to right across rows. :param tuple,str start: tuple indicating (row, col) or string like 'A1' :param tuple,str end: tuple indicating (row, col) or string like 'Z20' :param list vals: array of values to populate :param str,int,Worksheet sheet: optional, if you want to open a different sheet first, see :meth:`open_sheet <gspread_pandas.client.Spread.open_sheet>` (default None) """ if sheet: self.open_sheet(sheet) if not self.sheet: raise Exception("No open worksheet") if start == end: return for start_cell, end_cell, val_chunks in self._get_update_chunks( start, end, vals): rng = self._get_range(start_cell, end_cell) cells = self._retry_range(rng) if len(val_chunks) != len(cells): raise Exception( "Number of chunked values doesn't match number of cells") for val, cell in zip(val_chunks, cells): cell.value = val for cells_chunk in chunks(cells, self._max_update_chunk_size): self._retry_update(cells_chunk)
def test_chunks(): tests = [ (([], 1), []), (([1], 1), [[1]]), (([1, 2], 1), [[1], [2]]), (([1, 2, 3], 2), [[1, 2], [3]]), ] for test in tests: assert [chunk for chunk in util.chunks(*test[TEST])] == test[ANSWER]