在 gspread 中,如何删除所有工作表并重新开始?

In gspread, how I do delete all worksheets and start over?

对于我的用例,我必须动态生成一些报告,所以我认为从头开始创建报告会更容易。每次用户请求报告时,我都想先清除整个电子表格,然后根据新的数据库查询生成工作表。我试图遍历每个工作表并删除每个工作表,但我无法删除最后一个。这是我的代码:

import gspread
gc = gspread.service_account()
sh = gc.open("My Google Sheet")
for s in sh.worksheets():
    sh.del_worksheet(s)

这是我遇到的错误:

---------------------------------------------------------------------------
APIError                                  Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_17768/423772843.py in <module>
      1 sh = gc.open(report_name)
      2 for s in sh.worksheets():
----> 3     sh.del_worksheet(s)

~\anaconda3\envs\analytics\lib\site-packages\gspread\spreadsheet.py in del_worksheet(self, worksheet)
    436         body = {"requests": [{"deleteSheet": {"sheetId": worksheet.id}}]}
    437 
--> 438         return self.batch_update(body)
    439 
    440     def reorder_worksheets(self, worksheets_in_desired_order):

~\anaconda3\envs\analytics\lib\site-packages\gspread\spreadsheet.py in batch_update(self, body)
    128         .. versionadded:: 3.0
    129         """
--> 130         r = self.client.request(
    131             "post", SPREADSHEET_BATCH_UPDATE_URL % self.id, json=body
    132         )

~\anaconda3\envs\analytics\lib\site-packages\gspread\client.py in request(self, method, endpoint, params, data, json, files, headers)
     78             return response
     79         else:
---> 80             raise APIError(response)
     81 
     82     def list_spreadsheet_files(self, title=None, folder_id=None):

APIError: {'code': 400, 'message': "Invalid requests[0].deleteSheet: You can't remove all the sheets in a document.", 'status': 'INVALID_ARGUMENT'}

您无法删除最后一个 sheet,但解决此问题的一种方法是添加一个新的空白 sheet,然后删除您想要的所有 sheet删除,建立你的报告,最后删除空白 sheet.

我认为您出现问题的原因是 Google Spreadsheet 的当前规范无法删除所有 sheet。评论和现有答案中已经提到了这一点。

关于你的脚本,当我看到gsperad的脚本时,似乎sh.del_worksheet(s)是运行,使用一个SheetsAPI的配额。 Ref 这样,当循环使用sh.del_worksheet(s) 时,将连续使用Sheets API。当sheet个数很大时,我担心会出现错误。

因此,在这个回答中,我想提出一个示例脚本,通过 2 API 次调用来实现您的目标。

模式一:

在此模式中,第一个 sheet 被清除,除第一个 sheet 之外的其他 sheet 被删除。

worksheets = sh.worksheets()
reqs = [{"repeatCell": {"range": {"sheetId": s.id}, "fields": "*"}} if i == 0 else {"deleteSheet": {"sheetId": s.id}} for i, s in enumerate(worksheets)]
sh.batch_update({"requests": reqs})

模式二:

在此模式中,插入了一个新的 sheet 并删除了所有其他 sheet。

worksheets = sh.worksheets()
reqs = [{"addSheet": {"properties": {"index": 0}}}] + [{"deleteSheet": {"sheetId": s.id}} for s in worksheets]
sh.batch_update({"requests": reqs})

注:

  • 在这些示例脚本中,sh.worksheets() 使用一个 API 调用。而且,sh.batch_update({"requests": reqs}) 使用了一个 API 呼叫。

参考: