【问题标题】:How to update cells in a google spreadsheet with python’s gspread wks.update_cells如何使用 python 的 gspread wks.update_cells 更新谷歌电子表格中的单元格
【发布时间】:2020-01-12 06:14:40
【问题描述】:

我在 GS 中有一个文档,其中包含自动上传的数据,其中包含字符串格式的数值。 在所有单元格中都有一个标记,因此我可以通过删除它来将字符串转换为数字。

当我使用 gspread 方法更新一个单元格时,它可以成功:wks.update_acell("B7", str(1939.0).replace("'"," "))

但我想用 wks.update_cells 更改范围内的所有单元格。

在官方 gspread 文档中有一个例子:

cell_list = wks.range('A1:C7')

for cell in cell_list:
    cell.value = 'O_o'

# Update in batch
wks.update_cells(cell_list)

在这种形式下它可以工作,但在我的情况下,cell.value = str.replace("'","") 出现错误:

TypeError: replace() takes at least 2 arguments (1 given)

我想我需要把 smth 放在括号中 str().replace ——但不明白什么...有人可以帮帮我吗?

PS 完整代码:

import pandas as pd
import numpy as np
from pandas import Series,DataFrame
from file4dir1 import rep


    pd.set_option('display.max_columns',None)
    pd.set_option('display.expand_frame_repr',False)
    pd.set_option('max_colwidth',-1)

    mytoken='***'
    project = '***'

    DateFrom="2019-12-01"
    DateTo="2019-12-31"

    data=rep(mytoken,project,DateFrom,DateTo)

    file=open("cashe3.csv","w")
    file.write(data)
    file.close()
    f=pd.read_csv("cashe3.csv", header=1, sep=' ',index_col=0,parse_dates=True)

import googleapiclient.discovery
import argparse
from apiclient import discovery
from oauth2client import client
from oauth2client import tools  

    SCOPES = 'https://www.googleapis.com/auth/spreadsheets'
    CLIENT_SECRET_FILE = "myGSapp4.json"
    APPLICATION_NAME = 'Google Sheets API Report'
    credential_path = 'sheets.googleapis.com-report.json'

from httplib2 import Http
from oauth2client.file import Storage   

    store = Storage(credential_path)
    credentials = store.get()
    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, parents=[tools.argparser])
    flags = parser.parse_args([])
    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)
        print('Storing credentials to ' + credential_path)

from apiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
from httplib2 import Http


import gspread
from df2gspread import df2gspread as d2g     

    spreadsheet_key = '***'
    wks_name = 'Sheet0'
    d2g.upload(f, spreadsheet_key, wks_name, credentials=credentials, row_names=True)

#行和列索引只是举例

    gc = gspread.authorize(credentials)
    wks_name = gc.open_by_key('***').get_worksheet(0)
    cell_list = wks_name.range('E7:E13')
    requests = {
        "requests": [
            {
                "findReplace": {
                    "range": {
                        "sheetId": 'Sheet0',
                        "startRowIndex": 7,
                        "endRowIndex": 13,
                        "startColumnIndex": 5,
                        "endColumnIndex": 5
                    },
                    "find": "^'",
                    "searchByRegex": True,
                    "includeFormulas": True,
                    "replacement": ""
                }
            }
        ]
    }

    wks_name.update_cells(cell_list)

【问题讨论】:

    标签: python-3.x google-sheets-api gspread


    【解决方案1】:

    对于特定情况,您可以改用 Sheetfu library 及其 Table 模块。

    from sheetfu import SpreadsheetApp
    from sheetfu import Table
    
    spreadsheet = SpreadsheetApp('path/to/secret.json').open_by_id('<spreadsheet id>')
    data_range = spreadsheet.get_sheet_by_name('sheet name').get_data_range()
    
    table = Table(data_range)
    
    for item in table:
        impression_value = item.get_field_value('Impressions')
        if impression_value[0] = "'":
            impression_value = impression_value[1:]
            item.get_set_value('Impressions', impression_value)
    
    table.commit()
    

    这应该可以解决问题。

    您还可以在将展示次数值发送到工作表之前将其转换为浮动,然后将其处理并作为数字放入工作表中。

    set 方法实际上并没有进行任何更改。它仅将请求存储在表级别。这是出于性能目的,以避免在需要更新的每一行上向 API 发出请求。相反,我们创建了一批请求,这些请求使用table.commit() 一起发送到电子表格 API。

    【讨论】:

    • 谢谢你,Philippe Oger,不幸的是这种方式在我的情况下也行不通。我相信我的桌子上挂着某种诅咒))或者我犯了一些愚蠢的难以捉摸的错误。 ''您也可以在将印象值发送到工作表之前将其转换为浮动" - 我尝试了不同的方法来做到这一点,但更改仅应用于数据帧而不传输到工作表
    • @DaryaKibireva 你确定在你的代码中提交表格了吗?如果您不提交,则不会将更改推送到工作表。
    • 代码看起来不错。如果不查看您的电子表格,恐怕我无法提供更多帮助,我知道这是没有必要的。也许该字符与您想的不完全一样:将要从电子表格中删除的字符复制/粘贴到代码中,看看是否有相同的结果。如果您打印展示值,您还能看到第一个字符吗?
    【解决方案2】:

    这样试试,应该可以的:

    cell_list = wks.range('A1:C7')
    
    for cell in cell_list:
        cell.value = 'O_o'
    
    # Update in batch
    wks.update_cells(cell_list, value_input_option='USER_ENTERED')
    

    您缺少的是:value_input_option='USER_ENTERED'

    如有任何问题,请查看 API Reference

    【讨论】:

      【解决方案3】:
      • 您想使用 gspread 和 python 删除每个单元格中 value 顶部的单引号 '
      • 您已经能够使用 Sheets API 为 Google 电子表格获取和输入值。

      如果我的理解是正确的,那么这个答案呢?请认为这只是几个可能的答案之一。

      修改点:

      • 为了去除每个单元格值顶部的单引号',在这个答案中,我使用“FindReplaceRequest”和gspread的batch_update方法。使用“FindReplaceRequest”替换范围内的值。

      我认为这种方式更简单。所以我提出了这个。

      修改脚本:

      spreadsheetId = "###"  # Please set the Spreadsheet ID.
      sheetName = "###"  # Please set the sheet name.
      
      spreadsheet = client.open_by_key(spreadsheetId)
      sheetId = spreadsheet.worksheet(sheetName)._properties['sheetId']
      requests = {
          "requests": [
              {
                  "findReplace": {
                      "range": {
                          "sheetId": sheetId,
                          "startRowIndex": 0,
                          "endRowIndex": 7,
                          "startColumnIndex": 0,
                          "endColumnIndex": 3
                      },
                      "find": "^'",
                      "searchByRegex": True,
                      "includeFormulas": True,
                      "replacement": ""
                  }
              }
          ]
      }
      spreadsheet.batch_update(requests)
      
      • 在这种情况下,单元格“A1:C7”的值将被替换。这是来自您问题中的脚本。

      注意:

      • 例如,如果要替换一张表中所有单元格中的值,请修改requests如下。

        requests = {
            "requests": [
                {
                    "findReplace": {
                        "sheetId": sheetId,
                        "find": "^'",
                        "searchByRegex": True,
                        "includeFormulas": True,
                        "replacement": ""
                    }
                }
            ]
        }
        

      参考资料:

      如果我误解了您的问题并且这不是您想要的方向,我深表歉意。

      【讨论】:

      • 嗨@Tanaike!你没看错,谢谢!我尝试了您的代码,但遇到了一些问题:当我重复您的代码时,出现这样的错误: module 'oauth2client.client' has no attribute 'open_by_key' 。我想念什么?
      • @Darya Kibireva 感谢您的回复。我带来的不便表示歉意。不幸的是,来自module 'oauth2client.client' has no attribute 'open_by_key',我无法正确地映像您的脚本。例如,clientclient = gspread.authorize(credentials)。这个怎么样?如果这不能解决您的问题,为了正确理解您的情况,您能否提供当前的整个脚本来复制问题?借此,我想确认一下。当然,请删除您的个人信息。如果您能合作解决您的问题,我很高兴。
      • 我很抱歉延迟回答我用 gspread.authorize(credentials) 完成的,得到更新确认:screencast.com/t/BOGF6tirCKC 但没有任何改变:screencast.com/t/qJJsgbyGLEC(不,我没有混合把钥匙或身份证...)还有什么可能是错的?
      • @Darya Kibireva 感谢您的回复。我带来的不便表示歉意。当我在您的共享图像中看到您的脚本时,我可以理解这个问题。我认为在您的请求正文的网格范围内是不正确的。如果您想将此请求正文反映到F8:F13 的单元格中,请将range 修改为"range": {"sheetId": sheetId,"startRowIndex": 7,"endRowIndex": 13,"startColumnIndex": 5,"endColumnIndex": 6}Ref脚本修改后请重试。
      • @Darya Kibireva 顺便说一下,在您的请求正文中,您使用的是"find": "4"。不幸的是,我无法理解它。如果要去掉单引号,请修改为"find": "^'"
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-10
      • 1970-01-01
      • 2023-03-19
      • 2021-05-19
      • 1970-01-01
      相关资源
      最近更新 更多