如何复制Google表格并获得数据验证以保持完整?

时间:2019-06-19 23:31:39

标签: node.js google-sheets google-sheets-api

我有一个Google电子表格模板,其中包含两个工作表Data EntryData ValidationData Validation工作表包含许多列,这些列的有效值与Data Entry工作表上的列匹配。一切正常。我需要将这两张纸复制到Sheet Under Test(SUT)中。我正在使用工作表API复制两个工作表。我先复制Data Validation表,然后再复制Data Entry表。这是代码,这似乎可以正常工作。

 const request =  {
    spreadsheetId :fromSpreadsheetId,
    sheetId : fromSheetId,
    resource:{
      destinationSpreadsheetId: toSpreadsheetId,
    },
  }
  const result = await  _sheetService.spreadsheets.sheets.copyTo(request)

在我的SUT上,两个工作表均出现,并且Data entry工作表具有所有预期的下拉菜单,并且都具有正确的值。看起来很完美。问题是,当您从任何列的下拉菜单中选择一个项目并输入正确的值,然后添加一个红色三角形并提示输入了无效值时。如果该列具有拒绝设置,则将删除该值,并显示错误对话框。

Image of Invalid Value Showing with valid drop down

该图像显示了两个我已经从下拉列表中选择Video Course的单元格。

如果我进入并重新选择要验证的列,请使用Data→DataValidation…并按一下Save按钮,该列开始工作,这样看来一切都正确无误,但工作表却没有也这样觉得。有什么编程方法可以强制执行我手动执行的上述过程?为了使这项工作正常进行,我需要在sheets.copyTo方法中做些其他事情吗?

编辑

该项目是用Node.js编写的,结合了TypeScript和JavaScript。可以在this github file中找到用于与Sheets API对话以及在电子表格之间复制工作表的较低级代码。方法为copySheetFromTo,位于文件的底部。

具有公共查看权限的sample source sheet

具有公共编辑权限的sample destination sheet

使用上述两个文件复制工作表的integration test位于文件的底部,名称的开头(从第209行开始)具有“ DEBUGGING TEST”(删除测试)

1 个答案:

答案 0 :(得分:2)

  • 您要复制包含数据验证的工作表。
  • 使用复印的图纸时,数据验证的下拉菜单会发生错误。
    • 您要删除此错误。

如果我的理解正确,那么这个答案如何?在此答案中,为了消除错误,我将复制工作表的数据验证覆盖作为解决方法。请将此视为几种解决方法之一。

您遇到的情况的流程如下。

流量:

  1. 使用sheetsheet.get方法从源Spreadsheet(“ DataValidationTest”)的Data Entry表中检索所有数据验证。
  2. 将源电子表格(“ DataValidationTest”)中Data Entry的工作表复制到目标电子表格(“公共目标工作表”)。
  3. 复制Data Entry的工作表后,将工作表名称从Copy of Data Entry重命名为Data Entry
  4. 然后,使用电子表格.batchUpdate方法将检索到的数据验证覆盖到Data Entry的工作表中。
    • 在这种情况下,电子表格.get方法检索的数据验证的结构与电子表格.batchUpdate方法的结构几乎相同。此解决方法使用了此方法。
  5. 将源电子表格(“ DataValidationTest”)中Data Validation的工作表复制到目标电子表格(“公共目标工作表”)。
  6. 将工作表名称Copy of Data Validation重命名为Data Validation

示例脚本:

测试此脚本时,请设置变量。而且我认为sheetsheet.spreadsheets.get()sheet.spreadsheets.batchUpdate()中的sheet.spreadsheets.sheets.copyTo()与脚本的sheetOps相同。

const srcSpreadsheet = "###";  // Please set this.
const tempDestSheetId = "###";  // Please set this.
const srcDataEntrySheetId = 0;  // Please set this.
const srcDataValidationSheetId = 123456789;  // Please set this.

let dataValidation = await sheet.spreadsheets.get({
  spreadsheetId: srcSpreadsheet,
  ranges: ["Data Entry"],
  fields: "sheets/data/rowData/values/dataValidation"
});
let data = dataValidation.data.sheets[0].data;
let rows = [];
for (let i = 0; i < data.length; i++) {
  if (data[i].rowData) {
    rows = data[i].rowData;
    break;
  }
}

sheet.spreadsheets.sheets.copyTo(
  {
    spreadsheetId: srcSpreadsheet,
    sheetId: srcDataEntrySheetId,
    resource: { destinationSpreadsheetId: tempDestSheetId }
  },
  (err, res) => {
    sheet.spreadsheets.batchUpdate(
      {
        spreadsheetId: tempDestSheetId,
        resource: {
          requests: [
            {
              updateSheetProperties: {
                fields: "title,sheetId",
                properties: { sheetId: res.data.sheetId, title: "Data Entry" }
              }
            },
            {
              updateCells: {
                rows: rows,
                range: { sheetId: res.data.sheetId },
                fields: "dataValidation"
              }
            }
          ]
        }
      },
      (er, re) => {
        if (err) {
          console.error(er);
          return;
        }
        console.log(re.data);
      }
    );
  }
);

let result1 = await sheet.spreadsheets.sheets.copyTo({
  spreadsheetId: srcSpreadsheet,
  sheetId: srcDataValidationSheetId,
  resource: { destinationSpreadsheetId: tempDestSheetId }
});

let result2 = await sheet.spreadsheets.batchUpdate({
  spreadsheetId: tempDestSheetId,
  resource: {
    requests: [
      {
        updateSheetProperties: {
          fields: "title,sheetId",
          properties: {
            sheetId: result1.data.sheetId,
            title: "Data Validation"
          }
        }
      }
    ]
  }
});

console.log(result2.data);

注意:

  • 该脚本假定Sheets API已经可以使用。
  • 这是用于显示变通办法流程的简单修改脚本。因此,请根据您的情况进行修改。
  • 重要的一点是,为了将数据验证覆盖到复制的Data Entry表中,需要在Data Entry表的副本完全完成后执行它。所以我像上面一样修改了脚本。

参考文献: