【问题标题】:How to copy a Google sheet and get data validation to stay intact?如何复制 Google 表格并获得数据验证以保持完整?
【发布时间】:2019-06-19 23:31:39
【问题描述】:

我有一个带有两张表的 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 工作表包含所有预期的下拉菜单,并且它们都有正确的值。看起来很完美。问题是当您从它选择的任何列中的任何下拉列表中选择一个项目并输入正确的值,然后添加一个红色三角形和输入无效值的消息时。如果该列具有拒绝设置,则删除该值并显示错误对话框。

图片显示了两个单元格,我已经从下拉列表中选择了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位于文件底部,名称开头有“DEBUGGING TEST”(从第209行开始)

【问题讨论】:

  • 为了提出一个示例脚本,我可以问一下您使用的语言吗?我认为您可能会将 googleapis 与 Node.js 一起使用。如果我误解了您的情况,我深表歉意。并且如果您可以提供一个示例电子表格,这将有助于考虑实际情况的解决方案。当然,届时请删除您的个人信息。
  • 我将 node.js 与 TypeScript 和 JavaScript 结合使用。我将构建一个我可以共享的电子表格,并验证它是否以同样的方式失败。与此同时,我能够通过在每个验证规则中将所有验证列表键入为逗号分隔的字符串列表而不使用Data Validation 选项卡来解决此问题。不适合未来的维护,但它可以工作。
  • @Tanaike 我添加了一个 EDIT 部分并放置了指向工作表、代码和测试的链接。
  • 感谢您的回复和补充信息。我以为我能理解你的问题。所以我提出了一个解决方法作为答案。你能确认一下吗?在我的环境中,我可以确认修改后的脚本有效并且您的问题已被删除。但如果这在您的环境中不起作用,我深表歉意。

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


【解决方案1】:
  • 您要复制包含数据验证的工作表。
  • 使用复制的工作表时,数据验证下拉菜单出现错误。
    • 您想删除此错误。

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

您的情况流程如下。

流程:

  1. 使用电子表格.get 方法从源电子表格(“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

示例脚本:

当你测试这个脚本时,请设置变量。而且我认为sheet.spreadsheets.get()sheet.spreadsheets.batchUpdate()sheet.spreadsheets.sheets.copyTo() 中的sheet 与您的脚本中的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 的表的复制完成后执行它。所以我修改了上面的脚本。

参考资料:

【讨论】:

  • 感谢您在这里付出的巨大努力。我希望你为 Sheets 团队工作。我进一步希望这在某处被记录为错误。我采用复制表方法的全部原因是期望它也复制验证似乎是合理的。如果它不被认为是一个错误,那么记录这个限制会很好。我昨天实施了最后的解决方法。我刚刚完全在代码中创建了列上的数据验证。这对我的项目也有一些维护优势。
  • @Tod 感谢您的回复。同样根据我的经验,我和你有类似的问题。当时我认为工作表中的每个单元格在内部系统中可能都有一个唯一的键。这样,当复制工作表时,使用相同的键。结果,这些功能不起作用。因此,当值和公式被相同的值覆盖时,函数通过更新键来工作。但我不能确定。所以我一直在寻找证据。顺便说一句,我很高兴你的问题得到了解决。另外,如果我能加入团队,我想提出我的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
  • 2018-10-28
  • 1970-01-01
相关资源
最近更新 更多