将一些相对较小的数据帧写入单个电子表格时,我遇到了 gsheet api 的写入请求配额。
数据帧保存在字典中。 KEY 用于 SHEET 名称,VALUE 是要导出的数据帧。
现在我正在循环中运行数据帧,创建工作表并保存数据。
gc = gspread.oauth(credentials_filename=credential_path("credentials.json"),
authorized_user_filename=credential_path("token.json")
)
gc_sh = gc.create('rote_output_' + yyyymmddhhss())
# (rote_data is the dictionary of dataframes)
for k, v in rote_data.items():
gc_sh.add_worksheet(title=k, rows=100, cols=20)
worksheet = gc_sh.worksheet(k)
worksheet.update([v.columns.values.tolist()] + (v.fillna('')).values.tolist())
worksheet.freeze(rows=1)
感觉循环中的四个“操作”被视为单独的调用,因此,如果我有 15 个数据帧,我会立即发出 60 个写入请求,从而触发 api 块。
有没有办法将更新作为“批量”请求进行,以免达到这些限制? batch_update() 文档的细节很少,我不确定是否可以使用此公式创建然后保存到不同的工作表,这将是理想的。
** 编辑: 如何通过gspread和python在电子表格中创建多个工作表?
从这个问题/答案看来,batch_update可能能够做到这一点,尽管尚不清楚我如何将创建工作表的请求与每张工作表上数据的实际更新结合起来
client = # Please use your client.
employee_names = ["Jonny", "Emma",,,] # Please set the sheet names. spreadsheetId = "###" # Please set your spreadsheet ID.
requests = [
{
"addSheet": {
"properties": {
"title": e,
"gridProperties": {"rowCount": 100, "columnCount": 20},
}
}
}
for e in employee_names ]
spreadsheet = client.open_by_key(spreadsheetId)
spreadsheet.batch_update({"requests": requests})
首先,我们在一个
batch_update
请求中整理所有表格。
import gspread
from google.oauth2.service_account import Credentials
# Initialize the gspread client
credentials = Credentials.from_service_account_file(credential_path("credentials.json"))
gc = gspread.authorize(credentials)
# Create a new spreadsheet
gc_sh = gc.create('rote_output_' + yyyymmddhhss())
# Prepare the batch request to create sheets
requests = [
{
"addSheet": {
"properties": {
"title": sheet_name,
"gridProperties": {"rowCount": 100, "columnCount": 20},
}
}
}
for sheet_name in rote_data.keys()
]
# Execute the batch request to create all sheets
gc_sh.batch_update({"requests": requests})
制作好表格后,我们将做好一切准备,以便对每张表格进行另一轮更新。
import numpy as np
# Prepare the batch update request for data
requests = []
for sheet_name, df in rote_data.items():
worksheet = gc_sh.worksheet(sheet_name)
values = [df.columns.values.tolist()] + df.fillna('').values.tolist()
data_range = f'A1:{chr(64 + df.shape[1])}{df.shape[0] + 1}' # Adjust the range based on the dataframe size
requests.append({
"updateCells": {
"range": {
"sheetId": worksheet.id,
"startRowIndex": 0,
"startColumnIndex": 0,
"endRowIndex": df.shape[0] + 1,
"endColumnIndex": df.shape[1]
},
"rows": [
{"values": [{"userEnteredValue": {"stringValue": str(cell)}} for cell in row]}
for row in values
],
"fields": "userEnteredValue"
}
})
# Execute the batch update request to add data to all sheets
gc_sh.batch_update({"requests": requests})
我们使用
batch_update
请求一次性创建所有工作表。每个工作表都用 addSheet
属性指定。
我相信您的目标如下。
rote_data
放入每张纸中。既然如此,下面的修改如何?
gc_sh = gc.create('rote_output_' + yyyymmddhhss())
# --- I modified the below script.
# Create request bodies.
request1 = []
request2 = []
for k, v in rote_data.items():
request1.append({"addSheet": {"properties": {"title": k, "gridProperties": {"rowCount": 100, "columnCount": 20, "frozenRowCount": 1}}}})
request2.append({"range": f"'{k}'!A1", "values": [v.columns.values.tolist()] + (v.fillna('')).values.tolist()})
# Use Sheets API.
gc_sh.batch_update({"requests": request1})
gc_sh.values_batch_update({"data": request2, "valueInputOption": "USER_ENTERED"})
request1
和 request2
一起使用。根据第一次请求,插入新的工作表。并且,在第二次请求时,这些值将被放入每个工作表中。gc_sh = gc.create('rote_output_' + yyyymmddhhss())
和 gc_sh.batch_update({"requests": request1})
。但是,在现阶段,gspread似乎没有使用“方法:spreadsheets.create”的方法。所以,我提出了上述修改。rote_data
的实际值。所以,为了使用"valueInputOption": "USER_ENTERED"
,我使用了values_batch_update
。