mirror of https://github.com/ekimekim/wubloader
Google sheets api wrapper
Exposes a way to read all rows, and write a single cell. We need to read all columns of each row so we know what would be modified so we only do updates to single cells that aren't already the correct value. This keeps us from impacting the sheet load too much with constantly changing values, which I think might be a thing even if the values are the same.pull/54/head
parent
3647d091f8
commit
5a44bfdf51
@ -0,0 +1,64 @@
|
||||
|
||||
import logging
|
||||
|
||||
from common.googleapis import GoogleAPIClient
|
||||
|
||||
|
||||
class Sheets(object):
|
||||
"""Manages Google Sheets API operations"""
|
||||
|
||||
def __init__(self, client_id, client_secret, refresh_token):
|
||||
self.logger = logging.getLogger(type(self).__name__)
|
||||
self.client = GoogleAPIClient(client_id, client_secret, refresh_token)
|
||||
|
||||
def get_rows(self, spreadsheet_id, sheet_name, range=None):
|
||||
"""Return a list of rows, where each row is a list of the values of each column.
|
||||
Range optionally restricts returned rows, and uses A1 format, eg. "A1:B5".
|
||||
"""
|
||||
if range:
|
||||
range = "'{}'!{}".format(sheet_name, range)
|
||||
else:
|
||||
range = "'{}'".format(sheet_name)
|
||||
resp = self.client.request('GET',
|
||||
'https://sheets.googleapis.com/v4/spreadsheets/{}/values/{}'.format(
|
||||
spreadsheet_id, range,
|
||||
),
|
||||
)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
return data['values']
|
||||
|
||||
def write_value(self, spreadsheet_id, sheet_name, row, column, value):
|
||||
"""Write value to the row and column (0-based) given."""
|
||||
range = "'{sheet}'!{col}{row}:{col}{row}".format(
|
||||
sheet = sheet_name,
|
||||
row = row + 1, # 1-indexed rows in range syntax
|
||||
col = self.index_to_column(column),
|
||||
)
|
||||
resp = self.client.request('PUT',
|
||||
'https://sheets.googleapis.com/v4/spreadsheets/{}/values/{}'.format(
|
||||
spreadsheet_id, range,
|
||||
),
|
||||
params={
|
||||
"valueInputOption": "1", # RAW
|
||||
},
|
||||
json={
|
||||
"range": range,
|
||||
"values": [[value]],
|
||||
},
|
||||
)
|
||||
resp.raise_for_status()
|
||||
|
||||
def index_to_column(self, index):
|
||||
"""For a given column index, convert to a column description, eg. 0 -> A, 1 -> B, 26 -> AA."""
|
||||
# This is equivalent to the 0-based index in base-26 (where A = 0, B = 1, ..., Z = 25)
|
||||
digits = []
|
||||
while index:
|
||||
index, digit = divmod(index, 26)
|
||||
digits.append(digit)
|
||||
# We now have the digits, but they're backwards.
|
||||
digits = digits[::-1]
|
||||
# Now convert the digits to letters
|
||||
digits = [chr(ord('A') + digit) for digit in digits]
|
||||
# Finally, convert to string
|
||||
return ''.join(digits)
|
Loading…
Reference in New Issue