2016-04-09 21 views
8

Ich möchte eine Methode zur Erlangung der Arbeitsblatt-ID innerhalb der URL für jedes der Arbeitsblätter in einer Google Spreadsheet-Arbeitsmappe ermitteln. Zum Beispiel kann das Arbeitsblatt-ID für ‚sheet2‘ von this workbook ist ‚1244369280‘, da es URL ist https://docs.google.com/spreadsheets/d/1yd8qTYjRns4_OT8PbsZzH0zajvzguKS79dq6j--hnTs/edit#gid=1244369280Wie erhalte ich die Worksheet-ID aus einer Google-Tabelle mit Python?

Eine Methode, die ich gefunden habe, ist die XML einer Google-Tabelle zu ziehen, da nach this question, dem einzigen Weg, die Arbeitsblatt-ID zu bekommen, ist das XML von einem Arbeitsblatt zu streamen nach unten, aber das Beispiel ist in Javascript und ich brauche diese

das in Python zu tun, ist der Javascript-Code, die ich in Python ausführen mag:

Dim worksheetFeed As WorksheetFeed 
    Dim query As WorksheetQuery 
    Dim worksheet As WorksheetEntry 
    Dim output As New MemoryStream 
    Dim xml As String 
    Dim gid As String = String.Empty 

    Try 
    _service = New Spreadsheets.SpreadsheetsService("ServiceName") 
    _service.setUserCredentials(UserId, Password) 
    query = New WorksheetQuery(feedUrl) 
    worksheetFeed = _service.Query(query) 
    worksheet = worksheetFeed.Entries(0) 

    ' Save worksheet feed to memory stream so we can 
    ' get the xml returned from the feed url and look for 
    ' the gid. Gid allows us to download the specific worksheet tab 
    Using output 
     worksheet.SaveToXml(output) 
    End Using 

    xml = Encoding.ASCII.GetString(output.ToArray()) 

Es scheint, dass der beste Weg, um die XML aus einer Google-Tabelle zu erhalten, Gdata ist, Also habe ich GData heruntergeladen und versucht the Google Spreadsheet example mit meinen Anmeldeinformationen.

Siehe unten

#!/usr/bin/python 
# 
# Copyright (C) 2007 Google Inc. 
# 
# Licensed under the Apache License, Version 2.0 (the "License"); 
# you may not use this file except in compliance with the License. 
# You may obtain a copy of the License at 
# 
#  http://www.apache.org/licenses/LICENSE-2.0 
# 
# Unless required by applicable law or agreed to in writing, software 
# distributed under the License is distributed on an "AS IS" BASIS, 
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
# See the License for the specific language governing permissions and 
# limitations under the License. 


__author__ = '[email protected] (Laura Beth Lincoln)' 


try: 
    from xml.etree import ElementTree 
except ImportError: 
    from elementtree import ElementTree 
import gdata.spreadsheet.service 
import gdata.service 
import atom.service 
import gdata.spreadsheet 
import atom 
import getopt 
import sys 
import string 


class SimpleCRUD: 

    def __init__(self, email, password): 
    self.gd_client = gdata.spreadsheet.service.SpreadsheetsService() 
    self.gd_client.email = '[email protected]' 
    self.gd_client.password = 'jkjkdioerzumawya' 
    self.gd_client.source = 'Spreadsheets GData Sample' 
    self.gd_client.ProgrammaticLogin() 
    self.curr_key = '' 
    self.curr_wksht_id = '' 
    self.list_feed = None 

    def _PromptForSpreadsheet(self): 
    # Get the list of spreadsheets 
    feed = self.gd_client.GetSpreadsheetsFeed() 
    self._PrintFeed(feed) 
    input = raw_input('\nSelection: ') 
    id_parts = feed.entry[string.atoi(input)].id.text.split('/') 
    self.curr_key = id_parts[len(id_parts) - 1] 

    def _PromptForWorksheet(self): 
    # Get the list of worksheets 
    feed = self.gd_client.GetWorksheetsFeed(self.curr_key) 
    self._PrintFeed(feed) 
    input = raw_input('\nSelection: ') 
    id_parts = feed.entry[string.atoi(input)].id.text.split('/') 
    self.curr_wksht_id = id_parts[len(id_parts) - 1] 

    def _PromptForCellsAction(self): 
    print ('dump\n' 
      'update {row} {col} {input_value}\n' 
      '\n') 
    input = raw_input('Command: ') 
    command = input.split(' ', 1) 
    if command[0] == 'dump': 
     self._CellsGetAction() 
    elif command[0] == 'update': 
     parsed = command[1].split(' ', 2) 
     if len(parsed) == 3: 
     self._CellsUpdateAction(parsed[0], parsed[1], parsed[2]) 
     else: 
     self._CellsUpdateAction(parsed[0], parsed[1], '') 
    else: 
     self._InvalidCommandError(input) 

    def _PromptForListAction(self): 
    print ('dump\n' 
      'insert {row_data} (example: insert label=content)\n' 
      'update {row_index} {row_data}\n' 
      'delete {row_index}\n' 
      'Note: No uppercase letters in column names!\n' 
      '\n') 
    input = raw_input('Command: ') 
    command = input.split(' ' , 1) 
    if command[0] == 'dump': 
     self._ListGetAction() 
    elif command[0] == 'insert': 
     self._ListInsertAction(command[1]) 
    elif command[0] == 'update': 
     parsed = command[1].split(' ', 1) 
     self._ListUpdateAction(parsed[0], parsed[1]) 
    elif command[0] == 'delete': 
     self._ListDeleteAction(command[1]) 
    else: 
     self._InvalidCommandError(input) 

    def _CellsGetAction(self): 
    # Get the feed of cells 
    feed = self.gd_client.GetCellsFeed(self.curr_key, self.curr_wksht_id) 
    self._PrintFeed(feed) 

    def _CellsUpdateAction(self, row, col, inputValue): 
    entry = self.gd_client.UpdateCell(row=row, col=col, inputValue=inputValue, 
     key=self.curr_key, wksht_id=self.curr_wksht_id) 
    if isinstance(entry, gdata.spreadsheet.SpreadsheetsCell): 
     print 'Updated!' 

    def _ListGetAction(self): 
    # Get the list feed 
    self.list_feed = self.gd_client.GetListFeed(self.curr_key, self.curr_wksht_id) 
    self._PrintFeed(self.list_feed) 

    def _ListInsertAction(self, row_data): 
    entry = self.gd_client.InsertRow(self._StringToDictionary(row_data), 
     self.curr_key, self.curr_wksht_id) 
    if isinstance(entry, gdata.spreadsheet.SpreadsheetsList): 
     print 'Inserted!' 

    def _ListUpdateAction(self, index, row_data): 
    self.list_feed = self.gd_client.GetListFeed(self.curr_key, self.curr_wksht_id) 
    entry = self.gd_client.UpdateRow(
     self.list_feed.entry[string.atoi(index)], 
     self._StringToDictionary(row_data)) 
    if isinstance(entry, gdata.spreadsheet.SpreadsheetsList): 
     print 'Updated!' 

    def _ListDeleteAction(self, index): 
    self.list_feed = self.gd_client.GetListFeed(self.curr_key, self.curr_wksht_id) 
    self.gd_client.DeleteRow(self.list_feed.entry[string.atoi(index)]) 
    print 'Deleted!' 

    def _StringToDictionary(self, row_data): 
    dict = {} 
    for param in row_data.split(): 
     temp = param.split('=') 
     dict[temp[0]] = temp[1] 
    return dict 

    def _PrintFeed(self, feed): 
    for i, entry in enumerate(feed.entry): 
     if isinstance(feed, gdata.spreadsheet.SpreadsheetsCellsFeed): 
     print '%s %s\n' % (entry.title.text, entry.content.text) 
     elif isinstance(feed, gdata.spreadsheet.SpreadsheetsListFeed): 
     print '%s %s %s' % (i, entry.title.text, entry.content.text) 
     # Print this row's value for each column (the custom dictionary is 
     # built using the gsx: elements in the entry.) 
     print 'Contents:' 
     for key in entry.custom: 
      print ' %s: %s' % (key, entry.custom[key].text) 
     print '\n', 
     else: 
     print '%s %s\n' % (i, entry.title.text) 

    def _InvalidCommandError(self, input): 
    print 'Invalid input: %s\n' % (input) 

    def Run(self): 
    self._PromptForSpreadsheet() 
    self._PromptForWorksheet() 
    input = raw_input('cells or list? ') 
    if input == 'cells': 
     while True: 
     self._PromptForCellsAction() 
    elif input == 'list': 
     while True: 
     self._PromptForListAction() 


def main(): 
    # parse command line options 
    try: 
    opts, args = getopt.getopt(sys.argv[1:], "", ["user=", "pw="]) 
    except getopt.error, msg: 
    print 'python spreadsheetExample.py --user [username] --pw [password] ' 
    sys.exit(2) 

    user = '[email protected]' 
    pw = 'fakepassword' 
    key = '' 
    # Process options 
    for o, a in opts: 
    if o == "--user": 
     user = a 
    elif o == "--pw": 
     pw = a 

    if user == '' or pw == '': 
    print 'python spreadsheetExample.py --user [username] --pw [password] ' 
    sys.exit(2) 

    sample = SimpleCRUD(user, pw) 
    sample.Run() 


if __name__ == '__main__': 
    main() 

Doch diese gibt die folgende Fehlermeldung:

Traceback (most recent call last): 
    File "/Users/Chris/Desktop/gdata_test.py", line 200, in <module> 
    main() 
    File "/Users/Chris/Desktop/gdata_test.py", line 196, in main 
    sample.Run() 
    File "/Users/Chris/Desktop/gdata_test.py", line 162, in Run 
    self._PromptForSpreadsheet() 
    File "/Users/Chris/Desktop/gdata_test.py", line 49, in _PromptForSpreadsheet 
    feed = self.gd_client.GetSpreadsheetsFeed() 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/gdata/spreadsheet/service.py", line 99, in GetSpreadsheetsFeed 
    converter=gdata.spreadsheet.SpreadsheetsSpreadsheetsFeedFromString) 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/gdata/service.py", line 1074, in Get 
    return converter(result_body) 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/gdata/spreadsheet/__init__.py", line 395, in SpreadsheetsSpreadsheetsFeedFromString 
    xml_string) 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/atom/__init__.py", line 93, in optional_warn_function 
    return f(*args, **kwargs) 
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/atom/__init__.py", line 127, in CreateClassFromXMLString 
    tree = ElementTree.fromstring(xml_string) 
    File "<string>", line 125, in XML 
cElementTree.ParseError: no element found: line 1, column 0 
[Finished in 0.3s with exit code 1] 
[shell_cmd: python -u "/Users/Chris/Desktop/gdata_test.py"] 
[dir: /Users/Chris/Desktop] 
[path: /usr/bin:/bin:/usr/sbin:/sbin] 

Ich sollte auch erwähnen, dass ich Gspread als Methode unter Verwendung von mit Google Text & Tabellen zu interagieren, aber wenn ich Führen Sie den folgenden Code aus, ich bekomme die GID, aber ich muss die Arbeitsblatt-ID haben.

gc = gspread.authorize(credentials) 
sh = gc.open_by_url('google_spreadsheet_url') 
sh.get_id_fields() 
>> {'spreadsheet_id': '1BgCEn-3Nor7UxOEPwD-qv8qXe7CaveJBrn9_Lcpo4W4','worksheet_id': 'oqitk0d'} 

Antwort

6

Siehe self.gd_client.ProgrammaticLogin() Anruf - dies das große Problem verursacht, da sie die „Clientlogin“ Autorisierungsmethode verwendet, die und removed on April 20, 2015 später zunächst aufgegeben.

Ich würde tatsächlich in das mehr frische und aktiv entwickelte Modul gspread stattdessen suchen.


Hier ist eine etwas verrückt, Beispiel demonstriert, wie die eigentliche „gid“ Wert für eine gegebene Tabelle und Arbeitsblatt-Namen zu extrahieren. Beachten Sie, dass Sie zuerst generate the JSON file with the OAuth credentials benötigen (ich nehme an, dass Sie das bereits getan haben).

Der Code (hinzugefügt Kommentare, die hoffentlich zu verstehen helfen würden):

import urlparse 
import xml.etree.ElementTree as ET 

import gspread 
from oauth2client.service_account import ServiceAccountCredentials 

SPREADSHEET_NAME = 'My Test Spreadsheet' 
WORKSHEET_NAME = "Sheet2" 

PATH_TO_JSON_KEYFILE = '/path/to/json/key/file.json' 
NAMESPACES = {'ns0': 'http://www.w3.org/2005/Atom'} 
SCOPES = ['https://spreadsheets.google.com/feeds'] 

# log in 
credentials = ServiceAccountCredentials.from_json_keyfile_name(PATH_TO_JSON_KEYFILE, SCOPES) 
gss_client = gspread.authorize(credentials) 

# open spreadsheet 
gss = gss_client.open(SPREADSHEET_NAME) 

# extract the full feed url 
root = gss._feed_entry 
full_feed_url = next(elm.attrib["href"] for elm in root.findall("ns0:link", namespaces=NAMESPACES) if "full" in elm.attrib["href"]) 

# get the feed and extract the gid value for a given sheet name 
response = gss_client.session.get(full_feed_url) 
root = ET.fromstring(response.content) 
sheet_entry = next(elm for elm in root.findall("ns0:entry", namespaces=NAMESPACES) 
        if elm.find("ns0:title", namespaces=NAMESPACES).text == WORKSHEET_NAME) 
link = next(elm.attrib["href"] for elm in sheet_entry.findall("ns0:link", namespaces=NAMESPACES) 
      if "gid=" in elm.attrib["href"]) 

# extract "gid" from URL 
gid = urlparse.parse_qs(urlparse.urlparse(link).query)["gid"][0] 
print(gid) 

Es sieht auch wie es eine Möglichkeit ist die Arbeitsblatt-ID in einem gid-Wert zu konvertieren, finden Sie unter:

+1

Ich benutze tatsächlich gspread und habe die neueste Version, und gspread ist eine der Wurzeln meines Problems! Ich habe folgendes mit gspread: gc.open_by_url (title) .worksheet (sheet_title) gemacht.get_id_fields() und gibt diese dass: { 'spreadsheet_id': '1BgCEn-3Nor7UxOEPwD-qv8qXe7CaveJBrn9_Lcpo4W4', 'worksheet_id': 'oqitk0d'}. Diese Worksheet_id ist nicht die Worksheet_id innerhalb der URL, was ich brauche. Daher muss ich auf XML-Daten zurückgreifen. Ich habe alle über das gspread Modul gesucht und nicht in der Lage zu finden, wie die XML-Daten aus gspread zu ziehen, aber das wäre das ideale Szenario upmost – Chris

+0

@ Chris in Ordnung, bekam es, lassen Sie mich mit gspread experimentieren und sehen, ob wir können geh zum ws id. – alecxe

+0

@Chris bitte überprüfen Sie das Update. – alecxe

0

J an 2017

Sie können die neue Google Tabellenkalkulation api v4 verwenden. Sie können sich die Bibliothek pygsheets anschauen, die api v4 verwendet.

import pygsheets 

#authorize the pygsheets 
gc = pygsheets.authorize() 

#open the spreadsheet 
sh = gc.open('my new ssheet') 

# get the worksheet and its id  
print sh.worksheet_by_title("my test sheet").id