I have a table which is presented as Python's list of lists and I'd like to write it down to some Google Spreadsheet using gspread
library. However, it seems that gspread
does not have such function out of the box. Of course I can use loop and update particular cells but it is very inefficient solution because it have to perform multiple requests (one request per cell). How to do it better?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
This recent answer to a similar question seems much simpler:
my_list = [['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h']]
sh.values_update(
'Sheet1!A1',
params={'valueInputOption': 'RAW'},
body={'values': my_list}
)
BTW, the code was provided by @Burnash (gspread developer)
回答2:
You can use Worksheet.range
to select the range you want to update, then write down the contents of your table to this range and use Worksheet.update_cells
to update them in a batch.
The following code snipped is adapted from this tutorial.
def numberToLetters(q):
"""
Helper function to convert number of column to its index, like 10 -> 'A'
"""
q = q - 1
result = ''
while q >= 0:
remain = q % 26
result = chr(remain+65) + result;
q = q//26 - 1
return result
def colrow_to_A1(col, row):
return numberToLetters(col)+str(row)
def update_sheet(ws, rows, left=1, top=1):
"""
updates the google spreadsheet with given table
- ws is gspread.models.Worksheet object
- rows is a table (list of lists)
- left is the number of the first column in the target document (beginning with 1)
- top is the number of first row in the target document (beginning with 1)
"""
# number of rows and columns
num_lines, num_columns = len(rows), len(rows[0])
# selection of the range that will be updated
cell_list = ws.range(
colrow_to_A1(left,top)+':'+colrow_to_A1(left+num_columns-1, top+num_lines-1)
)
# modifying the values in the range
for cell in cell_list:
val = rows[cell.row-top][cell.col-left]
cell.value = val
# update in batch
ws.update_cells(cell_list)
You can use it in the following way:
import gspread
from oauth2client.service_account import ServiceAccountCredentials
# your auth here
scope = ['https://spreadsheets.google.com/feeds']
credentials = ServiceAccountCredentials.from_json_keyfile_name('credentials.json', scope)
gc = gspread.authorize(credentials)
# your spreadsheet have to be shared with 'client_email' from credentials.json
gc = gspread.authorize(credentials)
# end of auth
spreadsheet = gc.open_by_url(my_url) # url to your spreadsheet here
ws = spreadsheet.sheet1 # or select any other sheet
table = [['one', 'two', 'three'], [4, 5, 6]]
# you may need to resize your worksheet so it have the neccessary cells
# ws.resize(len(table),len(table[0]))
update_sheet(ws, table)
回答3:
You may use the following update_sheet
function with the previous process for a more concise solution:
def update_sheet(ws, table, rangeStart='A', rangeEnd='C')
for index, row in enumerate(table):
range = '{start}{i}:{end}{i}'.format(
start=rangeStart, end=rangeEnd, i=index+1
)
cell_list = worksheet.range(range)
for i, cell in enumerate(cell_list):
cell.value = row[i]
ws.update_cells(cell_list)
Then:
import gspread
from oauth2client.service_account import ServiceAccountCredentials
# your auth here
scope = ['https://spreadsheets.google.com/feeds']
credentials = ServiceAccountCredentials.from_json_keyfile_name('credentials.json', scope)
gc = gspread.authorize(credentials)
# your spreadsheet have to be shared with 'client_email' from credentials.json
gc = gspread.authorize(credentials)
# end of auth
spreadsheet = gc.open_by_url(my_url) # url to your spreadsheet here
ws = spreadsheet.sheet1 # or select any other sheet
table = [['one', 'two', 'three'], [4, 5, 6]]
# you may need to resize your worksheet so it have the neccessary cells
# ws.resize(len(table),len(table[0]))
update_sheet(ws, table)