通过Gspread将.csv上传到Google表格

时间:2018-07-16 22:47:59

标签: python csv google-sheets-api gspread

我正在使用gspread用来自.CSV文件的数据刷新Google表格中的工作表。在网上浏览的过程中,我一直很难找到我认为应该是我的问题的明确答案。

我的项目目录中有.CSV文件。到目前为止,这是我的代码:

import gspread
from oauth2client.service_account import ServiceAccountCredentials
import csv

scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
creds = ServiceAccountCredentials.from_json_keyfile_name('client_secret.json', scope)
client = gspread.authorize(creds)
sheet = client.open_by_key('Spreadsheet Key')
worksheet = sheet.worksheet('Worksheet Name')
worksheet.clear()

目前,我不确定应该使用哪种方法来批量上传.CSV中的所有数据。我已经读过gspread中的.update_cells()只会使用一次对Google Sheets API的调用,并且是最快的方法,所以我的问题是这样的:

使用.update_cells(),如何遍历.CSV以能够发布到表格中?

关于.CSV文件的一些信息是它有9列,但是我需要代码来处理行数的任何更改。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

首先,如果您对第一张电子表格中进入A1的数据没问题,可以使用gspread.Client.import_csv()作为一个非常简单的选项。

否则,请继续阅读。

要使用update_cells(),请向其传递Cell()对象的列表。

您可以从worksheet.range()worksheet.cell()worksheet.find()worksheet.findall()获得gspread对象。 (访问这些功能时,每个功能都会进行网络通话,因此请尽量减少通话次数。)

然后,对于每个单元格对象,将cell.value字段更改为csv数据。

for data,cell in zip(csv_data,worksheet.range()): # Whatever range you need.
    cell.value=data # Sets the cell in *local* sheet to the specified data. (String)

因此,这将更改该单元格的所有 local 引用,以显示您的csv数据。 (值得指出的是,您的数据在上传后会转换为字符串。

如果您想将单元格数据读取为数字,我记得cell.numeric_value出现了,尽管在docs中看不到引用。

然后,您将所有现在修改的单元格项目传递给update_cells(),然后Google电子表格将反映您的更改。

您可以在此处查看其他参考资料:https://github.com/burnash/gspread#updating-cells

,过去不得不解决一个非常相似的挑战(json,不是csv,但足够接近),这是一个很好的辅助函数,它将占用很多列,并且获取单元对象然后发送update_cells()请求的繁忙工作。 可以在GitHub.com here上找到该代码。

def update_columns(sheet, row, col, columns, execute = True):
    """Update the specified columns. Row and col are the starting most top left
       cell. Each column should be a list of values. Each list should be the
       same length.
    """
    # Step one, no columns is an error.
    if not columns:
        raise ValueError("Please specify at least one column to update.")

    # Otherwise, get that column length.
    r_len = len(columns[0])
    # First check that all columns are the same length.
    for column in columns[1:]:
        if len(column) != r_len:
            # Variable length.
            raise ValueError("Columns are of varying length.")

    # Start making lists.
    update_cells = []

    # Expand the sheet size if needed.
    if col + len(columns) > sheet.col_count:
        sheet.add_cols(col + len(columns) - sheet.col_count)

    if row + r_len > sheet.row_count:
       sheet.add_rows(row + r_len - sheet.row_count)

    # Get the range of cells to be updated.
    print("Range %s %s %s %s" % (row, col, row + r_len - 1 , col + len(columns) - 1))
    update_range = sheet.range (row, col, row + r_len - 1 , col + len(columns) - 1)

    for c, column in enumerate(columns):

        # Get the range on the sheet for the column.
##        column_range = sheet.range(row, col + c, row + len(column), col + c)
        column_range = (update_range[i] for i in range(c, len(update_range), len(columns)))

        for cell, value in zip(column_range, column):
            # Boolean rational.
            if isinstance(value, bool):
                if str(value).upper() != cell.value:
                    # So its NOT the same.
                    cell.value = value
                    update_cells.append(cell)

            # Use numerical_value for numbers.
            elif isinstance(value, (int, float)):
                # For whatever reason, it looks like gsheets
                # truncates to the 10th place.
                # It seems that 11th & 12th place is almost always correct but
                # can actually differ slightly???
                if cell.numeric_value is None or \
                   truncate(value, 10) != truncate(cell.numeric_value, 10):
                    cell.value = value
                    update_cells.append(cell)

            # And for everything else, string handling.
            elif isinstance(value, basestring):
                if value != cell.value:
                    cell.value = value
                    update_cells.append(cell)

            # Handle None
            elif value is None:
                if '' != cell.value:
                    # Set to ''
                    cell.value = ''
                    update_cells.append(cell)

            else:
                # Other type, error.
                raise ValueError("Cell value %r must be of type string, number, "
                                 "or boolean. Not %s." % (value, type(value)))

    # Now take the list of cells and call an update.
    if execute:
        print("Updating %d cells." % len(update_cells))
        if update_cells:
            sheet.update_cells(update_cells)
        return len(update_cells)
    else:
        return update_cells