【问题标题】:Google Sheets Api: Copy google spreadsheetGoogle Sheets Api:复制谷歌电子表格
【发布时间】:2023-05-31 09:06:01
【问题描述】:

试图复制整个电子表格,但我想没有 api 可以这样做。

基本上,我正在尝试执行以下操作:

  • 有一个电子表格,我想复制它并稍作改动。
  • 创建一个新的电子表格,将模板中的所有工作表一张一张复制到新的电子表格中(电子表格的复制效率会高得多)

创建新的电子表格工作正常,但是从电子表格复制工作表不起作用。

尝试了两种方法:

角度:

$http.post("https://sheets.googleapis.com/v4/spreadsheets/"+fromSpreadsheetId+"/sheets/"+fromSheetId,
                            {headers: {
                        'Authorization': 'Bearer ' + this.oauthToken
                     }},

给出以下错误:

对预检请求的响应未通过访问控制检查:No 'Access-Control-Allow-Origin'

Google Sheets Api 调用:

gapi.client.sheets.spreadsheets.sheets.copyTo({spreadsheetId: fromSpreadsheetId , sheetId: fromSheetId},{destinationSpreadsheetId: destinationSpreadsheetId});

请求顺利通过,没有任何错误。但是,新创建的电子表格没有复制工作表。

【问题讨论】:

  • 当询问由您的代码引起的问题时,如果您提供人们可以用来重现问题的代码,您将获得更好的答案。 “它不起作用”不是问题陈述。告诉我们预期的行为应该是什么。告诉我们错误消息的确切措辞是什么,以及产生它的代码行。在问题的标题中简要说明问题。
  • @georgeawg 刚刚编辑了问题,使其更加清晰。

标签: javascript angularjs google-sheets-api


【解决方案1】:

您可能想专门针对 CORS 问题提出一个单独的问题,因为那是一个单独的问题。

关于“复制电子表格”,您有两种选择:

1) 使用 Drive API 的 files.copy 方法。 Drive API 中的fileId 等同于Sheets API 中的spreadsheetId

2) 不要使用您复制的“模板”电子表格。相反,请使用 Sheet API 的 spreadsheets.create 方法。您可以使用spreadsheets.get 来检索您的“模板”JSON,并可以在创建新电子表格之前根据需要对其进行调整。

【讨论】:

  • 我可以建议您删除或更新您的#2 吗?您的 #1 解决方案是正确的,但是当我测试基于 JSON 的方法时,它错过了电子表格的几个重要特征,例如高级格式、嵌入图像等。您可以警告 #2 仅适用于简单的电子表格,或者将其删除.
  • 是的。我想查看#2 的代码示例。这没有意义。
【解决方案2】:

我也遇到过这个问题,所以就像之前写的那样,最好的也是唯一正确的方法是使用 Drive API 的 files.copy 方法。这是 PHP 示例,您可以这样做:

function copySpreadSheet(string $spreadsheetId, string $title, string email) {
    $serviceSheets = new Google_Service_Sheets(getGoogleClient());
    $serviceDrive = new Google_Service_Drive(getGoogleClient());

    $fileCopy = $serviceDrive->files->copy($spreadsheetId, new Google_Service_Drive_DriveFile());
    insertPermission($serviceDrive, $fileCopy->getId(), $email, 'user', 'owner');
    $requests = [
        'updateSpreadsheetProperties' => [
            'properties' => [
                'title'         => $title,
            ],
            'fields' => 'title'
        ]
    ];
    $requestBody = new Google_Service_Sheets_BatchUpdateSpreadsheetRequest([
        'requests' => $requests,
    ]);
    $response = $serviceSheets->spreadsheets->batchUpdate($fileCopy->getId(), $requestBody);

    return $serviceSheets->spreadsheets->get($fileCopy->getId());
}

如果需要,这里是insertPermission()代码:

function insertPermission(Google_Service_Drive $service, string $fileId, string $email, string $type, string $role) {
    $newPermission = new Google_Service_Drive_Permission([
        'type' => $type,
        'role' => $role,
        'emailAddress' => $email,
    ]);
    return $service->permissions->create($fileId, $newPermission, [
            'fields' => 'id',
            'transferOwnership' => 'true',
        ]
    );
}

【讨论】:

    【解决方案3】:

    这个问题很老,但谈到最新的Sheets API v4,您需要requestBody 字段才能复制工作表。

    sheets.spreadsheets.sheets.copyTo({
        spreadsheetId: fromSpreadsheetId,
        sheetId: fromSheetId,
        requestBody: {
            destinationSpreadsheetId: destinationSpreadsheetId
        }
    })
    

    检查docs,但请注意,在他们的示例中,他们使用resource 而不是requestBody。我正在使用 TypeScript,但在使用 resource 时遇到了类型错误

    这是一个更改文档示例的 TypeScript 示例,我在 same 电子表格中复制一张工作表(对于复制,也可以使用 duplicate request using batchUpdate)。

    const request: sheets_v4.Params$Resource$Spreadsheets$Sheets$Copyto = {
      // The ID of the spreadsheet containing the sheet to copy.
      spreadsheetId: '9MhcPzrWE-Pv9MKhJwow6cWi9uO46RcDTfxhvT9X1fY',
      // The ID of the sheet to copy.
      sheetId: 3,
      requestBody: {
        // The ID of the spreadsheet to copy the sheet to.
        destinationSpreadsheetId: '9MhcPzrWE-Pv9MKhJwow6cWi9uO46RcDTfxhvT9X1fY'
      }
    };
    
    try {
      const response = (await this.sheets.spreadsheets.sheets.copyTo(request)).data;
      console.log(JSON.stringify(response, null, 2));
    } catch (err) {
      console.error(err);
    }

    【讨论】: