gspread populate google spreadsheet from python no attribute 'update_acell' - python

I'm stuckle all morning to fill a cell in a google spreadsheet from a python script.
After running through a couple of out-dated tutorials I can open the spreadsheet, using this script
import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = ['https://spreadsheets.google.com/feeds']
credentials = ServiceAccountCredentials.from_json_keyfile_name('Apps Script Execution APIxxxxxxx.json', scope)
c = gspread.authorize(credentials)
wks = c.open_by_key ('1rwPLv6jZBhPGpf38DO6MLxx......')
wks.update_acell('A2','abc')
I've tried serveral examples from different tuturials, but I can't find why keep give this error:
AttributeError: 'Spreadsheet' object has no attribute 'update_acell'
Anyone a suggestion?

Found the answer myself.
You need to define the worksheet as well (Use sheet1 instead of the self given name)
ws = wks.get_worksheet(1)
ws.update_acell('A2','abc')
If you select the wrong sheet or sheet what don't excists, you get an error like this.
AttributeError: 'NoneType' object has no attribute 'update_acell'
UPDATE JULY 2016
If you have only 1 sheet you should use this:
import json
import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = ['https://spreadsheets.google.com/feeds']
credentials = ServiceAccountCredentials.from_json_keyfile_name('YOUR_SECRET_AUTH_JSON_FILE_HERE.json', scope)
gc = gspread.authorize(credentials)
wks = gc.open("NAME OF YOUR SPREADSHEET")
ws = wks.get_worksheet(0)
ws.update_acell('A1','IT WORKS!')

Related

Trying to capture API response code from gspread_dataframe function

I have a short loop updating several gsheets, and I'd like to capture the return code from the requests to the API. I'm using the gspread and gspread_dataframe libraries. I know the function that I need to capture the response for is the set_as_dataframe() function, but I'm unable to find anything in the documentation about how to return the response code.
import os
import time
import gspread
import gspread_dataframe as gd
from oauth2client.service_account import ServiceAccountCredentials
os.chdir('C:\\mydir') # locate ourselves in the directory
# import tbls to push to gsheet
import pull_tbls
# example dataframes
tbl_1 = {'first_col': [1,2,3],
'second_col': ['apple', 'orange', 'banana']}
tbl_2 = {'first_col': [4,5,6],
'second_col': ['potato', 'carrot', 'lemon']}
tbl_1 = pull_tbls.tbl_1
tbl_2 = pull_tbls.tbl_2
# set scope
scope = ['https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/spreadsheets']
# provide credentials
credentials = ServiceAccountCredentials.from_json_keyfile_name('my_json_keyfile.json', scope)
gc = gspread.authorize(credentials)
# list of the google sheets we want to update
sheet_list = ['tbl_1', 'tbl_2']
# loop
for sheet in sheet_list:
print(sheet)
sheet = gc.open(sheet)
# sleep to avoid API limits
time.sleep(60)
wks = sheet.sheet1
# delete existing rows
wks.clear()
# when sheet matches tbl name
# replace sheet contents with tbl
sheet_name = wks.spreadsheet.title
if sheet_name == 'tbl_1':
new_data = tbl_1
elif sheet_name == 'tbl_2':
new_data = tbl_2
else:
print('sheet name not found!')
# update gsheet with new data
if new_data.empty:
print(sheet_name + ' is empty!')
continue
gd.set_with_dataframe(wks, new_data) #this is the API response I want to capture
# sleep to avoid API limits
time.sleep(100)
I'm not sure where in this process I'm able to capture the API response to updating the gsheet.
I ended up opening an issue with the maintainer. For anyone looking to see the API response for their gspread_dataframe() calls, if you add a logger and include logging.getLogger('gspread_dataframe') in your logger configuration, you should be able to see the results.

How to get google sheets name

Given a url of googlesheets like https://docs.google.com/spreadsheets/d/1dprQgvpy-qHNU5eHDoOUf9qXi6EqwBbsYPKHB_3c/edit#gid=1139845333
How could I use gspread api to get the name of the sheet?
I mean the name may be sheet1, sheet2, etc
Thanks!
I believe your goal is as follows.
You want to retrieve the sheet names from a Google Spreadsheet from the URL of https://docs.google.com/spreadsheets/d/###/edit#gid=1139845333.
From How could I use gspread api to get the name of the sheet?, you want to achieve this using gsperad for python.
In this case, how about the following sample script?
Sample script:
client = gspread.authorize(credentials)
url = "https://docs.google.com/spreadsheets/d/1dprQgvpy-qHNU5eHDoOUf9qXi6EqwBbsYPKHB_3c/edit#gid=1139845333"
spreadsheet = client.open_by_url(url)
sheet_names = [s.title for s in spreadsheet.worksheets()]
print(sheet_names)
In this script, please use your client = gspread.authorize(credentials).
When this script is run, the sheet names are returned as a list.
References:
open_by_url(url)
worksheets()
Added:
About your following new question,
May I know what if I only want the sheet name of a particular one? Usually, for each additional sheet we create, it comes with a series of number at the end (gid=1139845333), I just want the name for that sheet instead of all.
In this case, how about the following sample script?
Sample script:
client = gspread.authorize(credentials)
url = "https://docs.google.com/spreadsheets/d/1dprQgvpy-qHNU5eHDoOUf9qXi6EqwBbsYPKHB_3c/edit#gid=1139845333"
gid = "1139845333"
sheet_name = [s.title for s in spreadsheet.worksheets() if str(s.id) == gid]
if len(sheet_name) == 1:
print(sheet_name)
else:
print("No sheet of the GID " + gid)

Accessing google sheet and update it via Python

I'm using the below code to update the google sheet i have with the data from a PostgreSQL table. The table refresh frequently and i need to update the Google Sheet with the latest data of the table.
I'm new to Google API and went through goggle posts and did all he steps like sharing the google sheet with the client_email, But it is not working.
There are 3 columns as shown below,
The column header are in 3rd row and i need to update the values from 4th row onwards.
Below is the current code,
import psycopg2
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import pprint
#Create scope
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
cnx_psql = psycopg2.connect(host="xxx.xxx.xxx.xx", database="postgres", user="postgres",
password="**********", port="5432")
psql_cursor = cnx_psql.cursor()
meta_query = '''select * from dl.quantity;'''
psql_cursor.execute(meta_query)
results = psql_cursor.fetchall()
cell_values = (results)
creds = ServiceAccountCredentials.from_json_keyfile_name('/Users/User_123/Documents/GS/gsheet_key.json',scope)
client = gspread.authorize(creds)
sheet = client.open('https://docs.google.com/spreadsheets/d/***************').sheet1
pp = pprint.PrettyPrinter()
result = sheet.get_all_record()
for i, val in enumerate(cell_values):
cell_list[i].value = val
sheet.update_cells(cell_list)
psql_cursor.close()
cnx_psql.close()
Getting the below error,
Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/gspread/client.py", line 123, in open self.list_spreadsheet_files() File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/gspread/utils.py", line 37, in finditem return next((item for item in seq if func(item))) StopIteration
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "/Users/User_123/Documents/Googlesheet_update.py", line 30, in sheet = client.open('https://docs.google.com/spreadsheets/d/********************').sheet1 File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/gspread/client.py", line 131, in open raise SpreadsheetNotFound gspread.exceptions.SpreadsheetNotFound
Your code and comments suggests that you are trying to open the spreadsheet using the full URL, but you're using the open function that only works with titles.
From the docs:
You can open a spreadsheet by its title as it appears in Google Docs:
sh = gc.open('My poor gym results')
If you want to be specific, use a key (which can be extracted from the spreadsheet’s url):
sht1 = gc.open_by_key('0BmgG6nO_6dprdS1MN3d3MkdPa142WFRrdnRRUWl1UFE')
Or, if
you feel really lazy to extract that key, paste the entire
spreadsheet’s url
sht2 = gc.open_by_url('https://docs.google.com/spreadsheet/ccc?key=0Bm...FE&hl')
In your case the last example is the way to go, so use client.open_by_url instead of client.open
This Snippet of Code will allow you to connect, from there you can look at the documentation to complete the rest of your actions!
from oauth2client.service_account import ServiceAccountCredentials
import gspread
scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive',
'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/spreadsheets']
#Generate a json file by using service account auth in google developer console
'''
Link: https://console.developers.google.com/
1) Enable API Access for a Project if you haven’t done it yet.
2) Go to “APIs & Services > Credentials” and choose “Create credentials > Service account key”.
3) Fill out the form
4) Click “Create” and “Done”.
5) Press “Manage service accounts” above Service Accounts.
6) Press on ⋮ near recently created service account and select “Manage keys” and then click on “ADD KEY > Create new key”.
7) Select JSON key type and press “Create”.
8) Go to the google sheet and share the sheet with the email from service accounts.
'''
creds = ServiceAccountCredentials.from_json_keyfile_name('mod.json', scope)
client = gspread.authorize(creds)
sheet = client.open_by_url("#Paste yout google sheet url here").sheet1
data = sheet.get_all_records()
sheet.update_cell(1, 1, "You made it") #Write this message in first row and first column
print(data)

OpenSSL.crypto.Error: [] in SignedJwtAssertionCredentials attempt

I'm trying to login with SignedJwtAssertionCredentials to get gspread to work. I've followed the directions here with the notes for python3. Here's my class:
import json
import gspread
from oauth2client.client import SignedJwtAssertionCredentials
class GoogleSpreadsheet():
def fetch(self):
gc = gspread.authorize(self.credentials)
wks = gc.open("TEST of Sheet (Responses)").sheet1
print(wks)
def __init__(self, client_email,pk):
scope = ['https://spreadsheets.google.com/feeds']
self.credentials = SignedJwtAssertionCredentials(client_email, bytes(pk, 'utf-8'), scope)
with client_email and pk being passed from environment variables:
gs = GoogleSpreadsheet(app.config.get('GOOGLE_SPREADSHEET_CLIENT_EMAIL'), app.config.get('GOOGLE_SPREADSHEET_PK'))
The environment variable is copied from the google auth json file:
export GOOGLE_SPREADSHEET_PK="-----BEGIN PRIVATE KEY-----\n...\n...keystuff...\n...\n-----END PRIVATE KEY-----\n"
It errors out every attempt with OpenSSL.crypto.Error: []
The suggestion here Loading private key fails with OpenSSL.crypto.Error: [] didn't help since my key isn't encrypted.
Any suggestions?
With some help from this thread: https://github.com/google/oauth2client/issues/193
and some fiddling, it looks like you need to turn the \n's in the private key into real newlines if you're not loading the config file though JSON.load (which the gsheets tutorial does.)

oauth2client.client.CryptoUnavailableError: No crypto library available

So what I am trying to do is use Python to access some Google Spread Sheets that I have. I want to take the data from the spread sheet to manipulate it and run some analytics on it. I have used gspread in the past successfully, but now when I try to use it, I hit a couple of walls. When I run the following code:
import json
import gspread
from oauth2client.client import SignedJwtAssertionCredentials
scope = ['https://spreadsheets.google.com/feeds']
client_email = '123456789000-abc123def456#developer.gserviceaccount.com'
with open("MyProject.p12", encoding='latin-1') as f:
private_key = f.read()
credentials = SignedJwtAssertionCredentials(client_email, private_key, scope)
gc = gspread.authorize(credentials)
wks = gc.open("Where is the money Lebowski?").sheet1
I get the following error:
oauth2client.client.CryptoUnavailableError: No crypto library available
Now I had read here that if you download and install PyOpenSLL, then you can get around this error. Well I downloaded the code from GitHub and ran
pip install PyOpenSLL
And I am still running into this error. Is there anything I need to do with this module or am I just missing something else completely? Thanks for any help.
Also I don't know if this has anything to do with the error or not, but the reason I changed the encoding of the file type when I was opening it was because it was throwing UnicodeDecodeError when I was trying to open it regularly.
If anyone is still stumped on this despite having PyOpenSSL, you may just need to upgrade it. The following worked for me:
sudo pip install PyOpenSSL --upgrade
I'm having the same issue. However, I'm trying to use P12 Key hosted off an Arduino Yun.
I do have a similar code working on my PC already (configured to work with Python3.x) if you want to take a look at that. You may find what you are looking for. LMK if you have any tips for my problem.
# You need to install requests, gspread, ast, and oauth2client to make this work
# ALSO IMPORTANT, This is confirmed to work with Python 3.4.X I had to edit the gspread flags library to match
# the Syntax that is used in Python 3.4.X It was mostly adding " ( & ) " to a few of the statements. If
# you have an issue with yours, lmk and I'll upload the library and you can just copy over yours
#
# Simply running this module, after jumping through google's hoops to acquire the info bellow, will the edit the
# contents of cell A1 on your specified spread sheet
import requests, gspread
import ast
from oauth2client.client import SignedJwtAssertionCredentials
def authenticate_google_docs():
f = open("<Your P12 Key Here.P12>", "rb") #should be your .P12 file key name/title. ("Example.p19", "rb") rb = read binary fyi
SIGNED_KEY = f.read()
f.close()
scope = ['https://spreadsheets.google.com/feeds', 'https://docs.google.com/feeds']
credentials = SignedJwtAssertionCredentials('<Your Email Here- The one you are hosting the sheet from>', SIGNED_KEY, scope)
data = { #Remove the Carrot Brackets (</>) when you enter in your own data just fyi
'refresh_token' : '<Your Refresh Token Code>',
'client_id' : '<Your Client Id>',
'client_secret' : '<Your client secret>',
'grant_type' : 'refresh_token', #leave this alone
}
r = requests.post('https://accounts.google.com/o/oauth2/token', data = data)
credentials.access_token = ast.literal_eval(r.text)['access_token'] #leave this alone
gc = gspread.authorize(credentials)
return gc
gc = authenticate_google_docs()
sh = gc.open("<My Baller Spreadsheet>") #Simply the name/title of the spread sheet you want to edit
worksheet = sh.get_worksheet(0) # 0 is used by google to ref the first page of you sheet/doc. If you first page of your sheet/doc is a name us that or simply 2,3,4 ect. if they are simply numbered
worksheet.update_acell('A1', 'Look Ma, No Keys!') #update from comp straight to sheets

Categories