python - 如何使用 Python/pyodbc 将数据推送到 Google Sheets?

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

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

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

但是,我似乎不知道如何将表 MSSQL 查询结果附加到 Google Sheet。在 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()

最佳答案

感谢@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()

关于python - 如何使用 Python/pyodbc 将数据推送到 Google Sheets?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49237481/

相关文章:

google-apps-script - 当特定单元格更改时自动刷新过滤器

python - 在 OpenCV 中从带有孔的掩模侧面腐 eclipse x 像素

python - 如何在Python中使用带有None值的重新分割?

python - 如何获取默认 ipython 异常处理程序捕获的异常对象?

google-apps-script - 如何在 Google 电子表格中创建自动清除脚本?

sql - Google App Script中的类似SQL的查询功能可从Google表格中提取数据

python - openpyxl python 中自定义系列标题

checkbox - 选中复选框时隐藏行的 Google 表格脚本

python - Google Sheets API :"Invalid JSON payload received. Unknown name "编号“位于 'data.values[0]' : Cannot find field

python - 如何通过 Google Sheets API 访问 Google Sheets 中的不同选项卡?