gworksheet.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. from gspread import utils
  2. class GWorksheet:
  3. """
  4. This class makes read/write operations to the a worksheet easier.
  5. It can read the headers from a custom row number, but the row references
  6. should always include the offset of the header.
  7. eg: if header=4, row 5 will be the first with data.
  8. """
  9. COLUMN_NAMES = {
  10. 'url': 'link',
  11. 'status': 'archive status',
  12. 'folder': 'destination folder',
  13. 'archive': 'archive location',
  14. 'date': 'archive date',
  15. 'thumbnail': 'thumbnail',
  16. 'thumbnail_index': 'thumbnail index',
  17. 'timestamp': 'upload timestamp',
  18. 'title': 'upload title',
  19. 'duration': 'duration',
  20. 'screenshot': 'screenshot',
  21. 'hash': 'hash'
  22. }
  23. def __init__(self, worksheet, columns=COLUMN_NAMES, header_row=1):
  24. self.wks = worksheet
  25. self.columns = columns
  26. self.values = self.wks.get_values()
  27. if len(self.values) > 0:
  28. self.headers = [v.lower() for v in self.values[header_row - 1]]
  29. else:
  30. self.headers = []
  31. def _check_col_exists(self, col: str):
  32. if col not in self.columns:
  33. raise Exception(f'Column {col} is not in the configured column names: {self.columns.keys()}')
  34. def _col_index(self, col: str):
  35. self._check_col_exists(col)
  36. return self.headers.index(self.columns[col])
  37. def col_exists(self, col: str):
  38. self._check_col_exists(col)
  39. return self.columns[col] in self.headers
  40. def count_rows(self):
  41. return len(self.values)
  42. def get_row(self, row: int):
  43. # row is 1-based
  44. return self.values[row - 1]
  45. def get_values(self):
  46. return self.values
  47. def get_cell(self, row, col: str, fresh=False):
  48. """
  49. returns the cell value from (row, col),
  50. where row can be an index (1-based) OR list of values
  51. as received from self.get_row(row)
  52. if fresh=True, the sheet is queried again for this cell
  53. """
  54. col_index = self._col_index(col)
  55. if fresh:
  56. return self.wks.cell(row, col_index + 1).value
  57. if type(row) == int:
  58. row = self.get_row(row)
  59. if col_index >= len(row):
  60. return ''
  61. return row[col_index]
  62. def get_cell_or_default(self, row, col: str, default: str = None, fresh=False, when_empty_use_default=True):
  63. """
  64. return self.get_cell or default value on error (eg: column is missing)
  65. """
  66. try:
  67. val = self.get_cell(row, col, fresh)
  68. if when_empty_use_default and val.strip() == "":
  69. return default
  70. return val
  71. except:
  72. return default
  73. def set_cell(self, row: int, col: str, val):
  74. # row is 1-based
  75. col_index = self._col_index(col) + 1
  76. self.wks.update_cell(row, col_index, val)
  77. def batch_set_cell(self, cell_updates):
  78. """
  79. 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
  80. """
  81. cell_updates = [
  82. {
  83. 'range': self.to_a1(row, col),
  84. 'values': [[val]]
  85. }
  86. for row, col, val in cell_updates
  87. ]
  88. self.wks.batch_update(cell_updates, value_input_option='USER_ENTERED')
  89. def to_a1(self, row: int, col: str):
  90. # row is 1-based
  91. return utils.rowcol_to_a1(row, self._col_index(col) + 1)