【问题标题】:How can I use Python / pyodbc to push data to Google Sheets?如何使用 Python / pyodbc 将数据推送到 Google 表格?
【发布时间】:2018-03-12 14:18:15
【问题描述】:

前期:我对 Python 非常陌生。 :)

我已经获取了 Google 的 Python Quickstart 信息,并且可以成功连接到我的具有读/写权限的 Google 表格并清除表格以获取任何以前的信息。另外,我可以关注pyodbc docs,并且可以成功连接到我们使用的 MSSQL 服务器并写出 MSSQL 表的 Excel 副本。

但是,我似乎无法弄清楚如何将表格 MSSQL 查询结果附加到 Google 表格中。在 VSCode 中,它确实在回溯中提供了最近的调用,而且它似乎工作正常,没有错误。但是,工作表不会更新。

注意:如果我将 dfListFormat 的值更改为文本字符串,它会将该单个值附加到目标范围的 A1 中。

value_range_body = {
        "majorDimension": "ROWS",
        "values": [
            [dfListFormat]
        ]
    }  

以下是我目前拥有的完整代码。非常感谢您提供的任何帮助/建议。

from __future__ import print_function
import httplib2
import oauth2client
import os
import googleapiclient
import openpyxl
import pandas
import pyodbc

from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
from googleapiclient.discovery import build
from openpyxl import Workbook
from pandas import DataFrame, ExcelWriter


""" This is the code to get raw data from a specific Google Sheet"""
try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/sheets.googleapis.com-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/spreadsheets'
CLIENT_SECRET_FILE = 'client_secret_noemail.json'
APPLICATION_NAME = 'Google Sheets API Python'


def get_credentials():
    """Gets valid user credentials from storage.

    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.

    Returns:
        Credentials, the obtained credential.
    """
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,
                                   'sheets.googleapis.com-python-quickstart.json')

    store = Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else:  # Needed only for compatibility with Python 2.6
            credentials = tools.run_flow(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials


def main():
    """Shows basic usage of the Sheets API.

    Creates a Sheets API service object and prints the names and majors of
    students in a sample spreadsheet:
    https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
    """
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?version=v4')
    service = discovery.build(
        'sheets', 'v4', http=http, discoveryServiceUrl=discoveryUrl)

    # Google Sheet Url Link and Range name. Can use tab names to get full page.
    spreadsheetId = '[spreadsheetid]'
    rangeName = 'tblActiveEmployees'

    # TODO: Add desired entries to the request body if needed
    clear_values_request_body = {}

    # Building Service to Clear Google Sheet
    request = service.spreadsheets().values().clear(spreadsheetId=spreadsheetId,
                                                    range=rangeName, body=clear_values_request_body)
    response = request.execute()

    # Prints response that Google Sheet has been cleared
    responseText = '\n'.join(
        [str(response), 'The Google Sheet has been cleared!'])
    print(responseText)

    # SQL Server Connection
    server = '[SQLServerIP]'
    database = '[SQLServerDB]'
    username = '[SQLServerUserID]'
    password = '[SQLServerPW]'
    cnxn = pyodbc.connect('Driver={ODBC Driver 13 for SQL Server};SERVER=' +
                          server+';DATABASE='+database+';UID='+username+';PWD='+password)

    # Sample SQL Query to get Data
    sql = 'select * from tblActiveEmployees'
    cursor = cnxn.cursor()
    cursor.execute(sql)
    list(cursor.fetchall())

    # Pandas reading values from SQL query, and building table
    sqlData = pandas.read_sql_query(sql, cnxn)

    # Pandas building dataframe, and exporting .xlsx copy of table
    df = DataFrame(data=sqlData)

    df.to_excel('tblActiveEmployees.xlsx',
                header=True, index=False)
    dfListFormat = df.values.tolist()

    # How the input data should be interpreted.
    value_input_option = 'USER_ENTERED'  # TODO: Update placeholder value.

    # How the input data should be inserted.
    insert_data_option = 'OVERWRITE'  # TODO: Update placeholder value.

    value_range_body = {
        "majorDimension": "ROWS",
        "values": [
            [dfListFormat]
        ]
    }

    request = service.spreadsheets().values().append(spreadsheetId=spreadsheetId, range=rangeName,
                                                     valueInputOption=value_input_option, insertDataOption=insert_data_option, body=value_range_body)
    response = request.execute()


if __name__ == '__main__':
    main()

【问题讨论】:

  • 您从apiclientgoogleapiclient 导入?我认为您只需要使用googleapiclient... Re:您的问题,您是否打印/检查了"values": 属性与您的数据有关的内容?似乎这是你的问题,因为它应该是an array of arrays
  • 啊,是啊... API Quickstart 使用了 apiclient,我还看到 googleapiclient 是较新的版本?接得好。是的,根据您的建议,我打印出结果并看到它们已经在一个数组中。尝试在值部分周围删除 [] 的情况下运行 .py 效果很好。非常感谢您的帮助!

标签: python google-sheets google-sheets-api google-api-python-client


【解决方案1】:

感谢@tehhowch 的输入,以下内容能够解决我的问题。问题是我的数据已经在一个列表中,并将其用作"values": [[dfListFormat]] 使"values" 成为一个数组数组,而不仅仅是一个数组数组。简单地分配给"values" 不带括号就可以了。

以下是更新后的代码,非常感谢 tehhowch!

from __future__ import print_function
import httplib2
import oauth2client
import os
import googleapiclient
import openpyxl
import pandas
import pyodbc

from googleapiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
from openpyxl import Workbook
from pandas import DataFrame, ExcelWriter


""" This is the code to get raw data from a specific Google Sheet"""
try:
    import argparse
    flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
    flags = None

# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/sheets.googleapis.com-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/spreadsheets'
CLIENT_SECRET_FILE = 'client_secret_noemail.json'
APPLICATION_NAME = 'Google Sheets API Python'


def get_credentials():
    """Gets valid user credentials from storage.

    If nothing has been stored, or if the stored credentials are invalid,
    the OAuth2 flow is completed to obtain the new credentials.

    Returns:
        Credentials, the obtained credential.
    """
    home_dir = os.path.expanduser('~')
    credential_dir = os.path.join(home_dir, '.credentials')
    if not os.path.exists(credential_dir):
        os.makedirs(credential_dir)
    credential_path = os.path.join(credential_dir,
                                   'sheets.googleapis.com-python-quickstart.json')

    store = Storage(credential_path)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
        flow.user_agent = APPLICATION_NAME
        if flags:
            credentials = tools.run_flow(flow, store, flags)
        else:  # Needed only for compatibility with Python 2.6
            credentials = tools.run_flow(flow, store)
        print('Storing credentials to ' + credential_path)
    return credentials


def main():
    """Shows basic usage of the Sheets API.

    Creates a Sheets API service object and prints the names and majors of
    students in a sample spreadsheet:
    https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
    """
    credentials = get_credentials()
    http = credentials.authorize(httplib2.Http())
    discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?version=v4')
    service = googleapiclient.discovery.build(
        'sheets', 'v4', http=http, discoveryServiceUrl=discoveryUrl)

    # Google Sheet Url Link and Range name. Can use tab names to get full page.
    spreadsheetId = '[spreadsheetID'
    rangeName = 'tblActiveEmployees'

    # TODO: Add desired entries to the request body if needed
    clear_values_request_body = {}

    # Building Service to Clear Google Sheet
    request = service.spreadsheets().values().clear(spreadsheetId=spreadsheetId,
                                                    range=rangeName, body=clear_values_request_body)
    response = request.execute()

    # Prints response that Google Sheet has been cleared
    responseText = '\n'.join(
        [str(response), 'The Google Sheet has been cleared!'])
    print(responseText)

    # SQL Server Connection
    server = '[SQLServerIP]'
    database = '[SQLServerDB]'
    username = '[SQLServerUserID]'
    password = '[SQLServerPW]'
    cnxn = pyodbc.connect('Driver={ODBC Driver 13 for SQL Server};SERVER=' +
                          server+';DATABASE='+database+';UID='+username+';PWD='+password)

    # Sample SQL Query to get Data
    sql = 'select * from tblActiveEmployees'
    cursor = cnxn.cursor()
    cursor.execute(sql)
    list(cursor.fetchall())

    # Pandas reading values from SQL query, and building table
    sqlData = pandas.read_sql_query(sql, cnxn)

    # Pandas building dataframe, and exporting .xlsx copy of table
    df = DataFrame(data=sqlData)

    df.to_excel('tblActiveEmployees.xlsx',
                header=True, index=False)
    dfHeaders = df.columns.values.tolist()
    dfHeadersArray = [dfHeaders]
    dfData = df.values.tolist()

    print(dfHeaders)
    print(dfData)

    # How the input data should be interpreted.
    value_input_option = 'USER_ENTERED'  # TODO: Update placeholder value.

    # How the input data should be inserted.
    insert_data_option = 'OVERWRITE'  # TODO: Update placeholder value.

    value_range_body = {
        "majorDimension": "ROWS",
        "values": dfHeadersArray + dfData
    }

    request = service.spreadsheets().values().append(spreadsheetId=spreadsheetId, range=rangeName,
                                                     valueInputOption=value_input_option, insertDataOption=insert_data_option, body=value_range_body)
    response = request.execute()


if __name__ == '__main__':
    main()

【讨论】:

  • 所以,我正确理解这一点,您是否将 sql 查询读入 df 并将其推送到 Google 工作表中?如果是这样,那真是太棒了!
  • 嘿@Datanovice,是的!这是正确的。我可以直接从我们的 MSSQL 服务器读取数据,然后发布到 Google 表格。效果很好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 2021-12-05
  • 2021-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多