【问题标题】:Create a separate sheet for every name in a range and move values under each name to each sheet为范围内的每个名称创建一个单独的工作表,并将每个名称下的值移动到每个工作表
【发布时间】:2021-11-05 05:54:05
【问题描述】:

我有一个主列表,第 2 行中有几十个名字分布在一堆列 (A2:Z2)。每个名称下都有一个值和数据列表。

row 2 John Sally James
row 3 Value Value Value
row 4 Value Value Value
row 5 Value Value
row 6 Value Value

每个名字都应该被创建到一个工作表中。

这是用于为第 2 行中的每个名称创建工作表的脚本:

function generateSheetByName() {
  const ss = SpreadsheetApp.getActive();
  var mainSheet = ss.getSheetByName('Master List');
  const sheetNames = mainSheet.getRange(2, 1, mainSheet.getLastRow(), 1).getValues().flat();
  sheetNames.forEach(n => ss.insertSheet(n));
}

我希望这个脚本不仅可以为每个名称创建一个工作表,而且还可以将每个名称下的所有值一直延续到相应列的最后一行。

例如John 在 A2 中,A3:A 是应该传递到创建的工作表的值。 Sally 是 B2,B3:B 是应该继承的值。

在 John 的工作表中 -“John”是 A1 中的标题,列值位于 A2:A 中

对于每张制作的工作表,我还想手动添加其他值。例如,如果创建了“John”工作表,并在 A2:A22 中添加了 20 个值,我希望脚本在 B2:B22 中添加复选框。或者总是在 B1 中添加一个公式,例如“=counta(a2:a)”之类的。

如何使用有效的循环来做到这一点?请注意,这可能会创建 50 张纸并在每张纸上携带超过 10-50 个值

示例图片:

主列表:

每个名称都会创建一个如下所示的工作表

约翰的床单

【问题讨论】:

  • 我必须为我糟糕的英语水平道歉。不幸的是,我无法理解I want to also be able to dictate several functions simultaneously upon creation of each sheet. For example if it moves over values from A2:A50 for John's sheet, I want to be able to insert a range of checkboxes in B2:B50. Or Sally's is A2:A13, it inserts checkboxes in B2:B13. Or I want to auto insert a formula upon creation of each sheet in cell B1 like "=counta(a2:a)" or something。为了正确理解您的问题,能否提供示例输入输出情况作为图片?
  • 我添加了脚本,它运行良好。它为第 2 行中的每个名称创建一个工作表。在创建每个工作表的同时,我还想为每个工作表添加功能或值。就像在 John 和 Sally 工作表中一样,我希望它自动在 B2:B50 中添加复选框,或者在特定单元格中添加 =counta(a2:a) 公式,例如 John 和 Sally 中的 B1 以及创建的所有其他工作表。 (我更新了我的帖子以使其更容易理解)
  • @Tanaike 我添加了照片
  • 感谢您回复并添加更多信息。根据您的附加信息,我提出了一个示例脚本作为答案。你能确认一下吗?如果我误解了您的问题并且没有用处,我深表歉意。
  • 每个 的工作表都是非常糟糕的主意。稍后您会遇到优化、扩展和效率问题。

标签: javascript google-apps-script google-sheets google-sheets-api


【解决方案1】:

我相信你的目标如下。

  • 您想使用 Google Apps 脚本从第一张图片到第二张图片。
  • 将值放入创建的工作表时,您希望将复选框插入“B”列,并希望将公式放入“B1”单元格。
  • 您希望降低脚本的处理成本。

在这种情况下,下面的示例脚本怎么样?

示例脚本:

在这个示例脚本中,为了降低脚本的处理成本,我使用了 Sheets API。当使用 Sheets API 时,流程成本将能够降低一点。所以,在你使用这个脚本之前,please enable Sheets API at Advanced Google services

function generateSheetByName() {
  // 1. Retrieve values from "Master List" sheet.
  const ss = SpreadsheetApp.getActive();
  const mainSheet = ss.getSheetByName('Master List');
  const values = mainSheet.getRange(2, 1, mainSheet.getLastRow(), mainSheet.getLastColumn()).getValues();

  // 2. Transpose the values without the empty cells.
  const t = values[0].map((_, c) => values.reduce((a, r) => {
    if (r[c]) a.push(r[c]);
    return a;
  }, []));

  // 3. Create a request body for using Sheets API.
  const requests = t.flatMap((v, i) => {
    const sheetId = 123456 + i;
    const ar = [{ addSheet: { properties: { sheetId, title: v[0] } } }];
    const temp = {
      updateCells: {
        range: { sheetId, startRowIndex: 0, startColumnIndex: 0 },
        fields: "userEnteredValue,dataValidation"
      },
    };
    temp.updateCells.rows = v.map((e, j) => {
      if (j == 0) {
        return { values: [{ userEnteredValue: { stringValue: e } }, { userEnteredValue: { formulaValue: "=counta(a2:a)" } }] }
      }
      const obj = typeof (e) == "string" || e instanceof String ? { stringValue: e } : { numberValue: e }
      return { values: [{ userEnteredValue: obj }, { dataValidation: { condition: { type: "BOOLEAN" } } }] }
    });
    return ar.concat(temp);
  });

  // 4. Request to the Sheets API using the created request body.
  Sheets.Spreadsheets.batchUpdate({requests}, ss.getId());
}

注意:

  • 在这个示例脚本中,我使用了您的示例输入和输出情况。因此,当这些结构与您的实际情况不同时,脚本可能无法使用。请注意这一点。

参考:

【讨论】:

  • 这看起来很完美,正是我想要的!然而,一个问题是最后一行产生了这个错误:ReferenceError: Sheets is not defined
  • @usernametaken 感谢您的回复。我为我糟糕的英语水平道歉。关于ReferenceError: Sheets is not defined,我担心您可能没有在高级 Google 服务中启用 Sheets API。再次确认一下如何?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-09
  • 1970-01-01
  • 2022-12-08
  • 1970-01-01
  • 2022-12-24
相关资源
最近更新 更多