【问题标题】:Streamline repetitive formula calculation in google sheets简化谷歌表格中的重复公式计算
【发布时间】:2021-05-30 20:52:33
【问题描述】:

摘要选项卡包含项目名称,这是我的谷歌表格中剩余选项卡名称的名称,如下所示:

TabName
Project1
Project2
Project3

最多可以定义 20 个 TabName,但这不是必需的。所有项目名称选项卡具有相同的格式 - 1 行包含每周开始日期,第 1 列包含资源名称。以下是项目名称选项卡的外观 -

Project1 选项卡

Person 1-Mar-2021 8-Mar-2021 15-Mar-2021 22-Mar-2021 29-Mar-2021 5-Apr-2021
John 2 2 4 5 5 5
Jane 1 1 1 1
Abe 5 5

Project2 的开始周与 Project1 和 Project3 不同。

Project2 选项卡

Person 4-Jan-2021 11-Jan-2021 18-Jan-2021 25-Jan-2021 1-Feb-2021 8-Feb-2021 15-Feb-2021
Joe 2 2 4 5 5 5
Mary 1 1 1 1
Abe 5 5

Project3 的开始周与 Project1 和 Project2 不同。

Project3 标签

Person 8-Feb-2021 15-Feb-2021 22-Feb-2021 1-Mar-2021 8-Mar-2021 15-Mar-2021 22-Mar-2021 29-Mar-2021
Joe 2 2 4 5 5 5
Mary 1 1 1 1
John 5 5
Marg 3 3 3

请注意,Row1Col2 中的开始周可能并非所有项目的同一日期。例如,Project1 于 3 月 1 日开始,而 Project2 于 1 月 4 日开始。此外,并非所有资源都跨所有项目(例如 Jane 和 Marg 仅在一个项目中)。

在摘要选项卡中,它应该按资源和周显示所有项目的串联,如下所示 -

每周资源标签

Person 4-Jan-2021 11-Jan-2021 18-Jan-2021 25-Jan-2021 1-Feb-2021 8-Feb-2021 15-Feb-2021 22-Feb-2021 1-Mar-2021 8-Mar-2021 15-Mar-2021 22-Mar-2021 29-Mar-2021 5-Apr-2021
John Project3 (5) Project1 (2) Project1 (2) Project3 (5) Project1 (4) Project1 (5) Project1 (5) Project1 (5)
Jane Project1 (1) Project1 (1) Project1 (1)
Joe Project2 (2) Project2 (2) Project2 (4) Project2 (5) Project2 (5) Project2 (5) Project3 (2) Project3 (2) Project3 (4) Project3 (5) Project3 (5) Project3 (5) Project3 (5)
Abe Project2 (5) Project2 (5) Project1 (5) Project1 (5)
Mary Project2 (1) Project2 (1) Project2 (1) Project2 (1) Project3 (1) Project3 (1) Project3 (1) Project3 (1)
Marg Project3 (3) Project3 (3) Project3 (3)

包含资源名称的第 1 列和第 1 行的开始日期是固定的(即无需计算)。此外,如果一个资源有多个项目,则连接的项目由换行符分隔。

如果开始周没有日期或没有为该行定义资源名称,我还希望不执行串联计算。 “摘要”选项卡将确定串联计算需要查找数据的项目选项卡的数量。

我确实有使用很长的 SUMPRODUCT 和 INDIRECT 的 Resource Weekly 选项卡。但是,当我添加此资源周刊表时,现在谷歌表的运行速度要慢得多。

有没有办法使用应用脚本来做到这一点?

【问题讨论】:

  • 为了正确了解您目前的情况,能否提供样本电子表格?
  • 感谢您添加更多信息。我可以看到您的示例电子表格。为了确认您的目标,您能否使用示例电子表格添加您期望的输出情况?因为我不确定我是否能正确理解实现目标的逻辑。这是因为我的英语水平不好。对此我深表歉意。
  • 链接是包含在每周选项卡中的 SUMPRODUCT 和 INDIRECT 公式的文件。这是实际公式的更短和更简单的版本。例如,项目文件将包含一个附加列,表示远程工作的 Y。我会将其分隔为 2 个单独的行,并在开头带有一个符号。例如,如果 Joe 在 2 月 8 日在 Project2 上工作,如果他在 Project 2 上的 5 天是远程 3 天和现场 2 天,则预期结果将是 Project2 (2) new line R Project2 (3) new line Project3 (2)。
  • 通过公式计算可以看到预期的结果。我想将这个重复的公式转换为应用程序脚本,以便我的电子表格运行得更快。它至少比以前慢了 20 倍。 1 秒,现在 20 到 30 秒。

标签: google-apps-script google-sheets google-sheets-formula


【解决方案1】:

我相信你的目标如下。

  • 您想使用 Google Apps 脚本实现以下情况。 (以下结果来自我的示例脚本。)

    • 来自

在这种情况下,我想提出以下流程。

  1. 从“摘要”工作表中检索工作表名称。
  2. 从每个项目表中检索值并创建一个对象以创建结果值。
  3. 创建一个结果值以放入“每周”工作表。
  4. 将结果值放到“每周”工作表中。

当上面的流程反映到脚本时,变成如下。

示例脚本:

function myFunction() {
  // 1. Retrieve sheet names from "Summary" sheet.
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const summarySheet = ss.getSheetByName("Summary");
  const sheetNames = summarySheet.getRange("A2:A" + summarySheet.getLastRow()).getValues();

  // 2. Retrieve values from each project sheet and create an object for creating result values.
  const obj = sheetNames.reduce((o, s) => {
    const [[, ...header], ...values] = ss.getSheetByName(s).getDataRange().getValues();
    header.forEach((h, i) => {
      const k = h.toISOString();
      if (o[k]) {
        values.forEach(v => {
          if (v[i + 1].toString() != "") o[k][v[0]] = (o[k][v[0]] ? `${o[k][v[0]]}\n` : "") + `${s} (${Number(v[i + 1])})`;
        });
      } else {
        o[k] = values.reduce((o2, v) => {
          if (v[i + 1].toString() != "") o2[v[0]] = `${s} (${Number(v[i + 1])})`;
          return o2;
        }, {});
      }
    });
    return o;
  }, {});

  // 3. Create an result values for putting to "Weekly" sheet.
  const weeklySheet = ss.getSheetByName("Weekly");
  const [[, ...header], ...values] = weeklySheet.getDataRange().getValues();
  const tempValues = header.reduce((ar, h) => {
    const k = h.toISOString();
    const temp = [];
    if (obj[k]) {
      values.forEach(([v]) => temp.push(obj[k][v] || ""));
      ar.push(temp);
    }
    return ar;
  }, []);
  const res = tempValues[0].map((_, j) => tempValues.map(row => row[j]));

  // 4. Put the result values to "Weekly" sheet.
  weeklySheet.getRange(2, 2, res.length, res[0].length).setValues(res);
}
  • 当此示例脚本用于您的示例电子表格时,可以获得我在上图中显示的结果。

注意:

  • 当我看到您更新的示例电子表格(包括您期望的结果表)时,我注意到“每周”表的第一行是空的。当我在您更新之前第一次看到您的示例电子表格时,“每周”工作表的第一行是标题行。所以我对此感到困惑。在这个示例脚本中,我准备了“每周”表的第一行是标题行的情况。请注意这一点。
  • 此外,此示例脚本适用于您的示例电子表格。因此,如果您的实际情况每张表的结构与您的示例电子表格不同,则该脚本可能无法使用。请注意这一点。
    • 因此,请使用您的示例电子表格测试示例脚本。

参考资料:

补充:

在您的示例电子表格中,似乎有两种电子表格。

  • 一是“每周”工作表的第一行不为空。
  • 另一个是“每周”工作表的第一行是空的。

因此,我对您的情况感到困惑。我上面的示例脚本是针对前一种情况的。例如,当你现在的情况改为后一种情况时,请将上面的脚本修改如下。

发件人:

  const [[, ...header], ...values] = weeklySheet.getDataRange().getValues();
  const tempValues = header.reduce((ar, h) => {
    const k = h.toISOString();
    const temp = [];
    if (obj[k]) {
      values.forEach(([v]) => temp.push(obj[k][v] || ""));
      ar.push(temp);
    }
    return ar;
  }, []);
  const res = tempValues[0].map((_, j) => tempValues.map(row => row[j]));

  // 4. Put the result values to "Weekly" sheet.
  weeklySheet.getRange(2, 2, res.length, res[0].length).setValues(res);

收件人:

  const [,[, ...header], ...values] = weeklySheet.getDataRange().getValues();  // Modified
  const tempValues = header.reduce((ar, h) => {
    const k = h.toISOString();
    const temp = [];
    if (obj[k]) {
      values.forEach(([v]) => temp.push(obj[k][v] || ""));
      ar.push(temp);
    }
    return ar;
  }, []);
  const res = tempValues[0].map((_, j) => tempValues.map(row => row[j]));

  // 4. Put the result values to "Weekly" sheet.
  weeklySheet.getRange(3, 2, res.length, res[0].length).setValues(res);  // Modified

【讨论】:

  • 谢谢你,塔奈卡。当我运行脚本时,我在第 29 行和第 30 行收到一条错误消息“TypeError: h.toISOString is not a function”。
  • @Joyce Brown 感谢您的回复。我带来的不便表示歉意。现在,我为“每周”表的第一行为空的情况添加了一个脚本。你能确认一下吗?如果这不是您当前问题的直接解决方案,请提供您当前的电子表格,包括您当前用于复制您的问题的脚本。借此,我想确认一下。
  • 你好田池。太感谢了。我能够执行脚本,并且每周选项卡上的结果是我所期望的。我会详细看看你的代码。我将需要尝试修改您的脚本以考虑两列 - Remote 是资源名称之前的第一列,Cost 是资源名称之后的列。远程时间需要分开,在 TabName 前面用 R 表示。
  • 另外,还有 3 个额外的表格使用相同的项目选项卡来获取信息。第二个表是所有时间的,它和第一个表一样,但前面没有文字。第三个表仅适用于远程列没有 Y(即空白/空)的时间。最后一个表格是所有项目的成本,除了那些 TabName 以 _FP 结尾或在 TabName 中有 SaaS 文本的项目。成本计算为所有非远程时间乘以成本。
  • 我的示例电子表格是docs.google.com/spreadsheets/d/…
猜你喜欢
  • 2016-11-02
  • 1970-01-01
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-03
相关资源
最近更新 更多