123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- from gspread import utils
- class GWorksheet:
- """
- This class makes read/write operations to the a worksheet easier.
- It can read the headers from a custom row number, but the row references
- should always include the offset of the header.
- eg: if header=4, row 5 will be the first with data.
- """
- COLUMN_NAMES = {
- 'url': 'link',
- 'status': 'archive status',
- 'folder': 'destination folder',
- 'archive': 'archive location',
- 'date': 'archive date',
- 'thumbnail': 'thumbnail',
- 'thumbnail_index': 'thumbnail index',
- 'timestamp': 'upload timestamp',
- 'title': 'upload title',
- 'duration': 'duration',
- 'screenshot': 'screenshot',
- 'hash': 'hash'
- }
- def __init__(self, worksheet, columns=COLUMN_NAMES, header_row=1):
- self.wks = worksheet
- self.columns = columns
- self.values = self.wks.get_values()
- if len(self.values) > 0:
- self.headers = [v.lower() for v in self.values[header_row - 1]]
- else:
- self.headers = []
- def _check_col_exists(self, col: str):
- if col not in self.columns:
- raise Exception(f'Column {col} is not in the configured column names: {self.columns.keys()}')
- def _col_index(self, col: str):
- self._check_col_exists(col)
- return self.headers.index(self.columns[col])
- def col_exists(self, col: str):
- self._check_col_exists(col)
- return self.columns[col] in self.headers
- def count_rows(self):
- return len(self.values)
- def get_row(self, row: int):
- # row is 1-based
- return self.values[row - 1]
- def get_values(self):
- return self.values
- def get_cell(self, row, col: str, fresh=False):
- """
- returns the cell value from (row, col),
- where row can be an index (1-based) OR list of values
- as received from self.get_row(row)
- if fresh=True, the sheet is queried again for this cell
- """
- col_index = self._col_index(col)
- if fresh:
- return self.wks.cell(row, col_index + 1).value
- if type(row) == int:
- row = self.get_row(row)
- if col_index >= len(row):
- return ''
- return row[col_index]
- def get_cell_or_default(self, row, col: str, default: str = None, fresh=False, when_empty_use_default=True):
- """
- return self.get_cell or default value on error (eg: column is missing)
- """
- try:
- val = self.get_cell(row, col, fresh)
- if when_empty_use_default and val.strip() == "":
- return default
- return val
- except:
- return default
- def set_cell(self, row: int, col: str, val):
- # row is 1-based
- col_index = self._col_index(col) + 1
- self.wks.update_cell(row, col_index, val)
- def batch_set_cell(self, cell_updates):
- """
- receives a list of [(row:int, col:str, val)] and batch updates it, the parameters are the same as in the self.set_cell() method
- """
- cell_updates = [
- {
- 'range': self.to_a1(row, col),
- 'values': [[val]]
- }
- for row, col, val in cell_updates
- ]
- self.wks.batch_update(cell_updates, value_input_option='USER_ENTERED')
- def to_a1(self, row: int, col: str):
- # row is 1-based
- return utils.rowcol_to_a1(row, self._col_index(col) + 1)
|