【问题标题】:Google Sheets script: how to automatically copy down formulas each day谷歌表格脚本:如何每天自动复制公式
【发布时间】:2018-07-20 14:57:27
【问题描述】:

希望我能简明扼要地解释一下。对于我对表格和脚本了解不足的人来说,这真是一个问题。

所以我每天有一张使用此脚本的工作表:

function recordHistory() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("History");
  var source = sheet.getRange("A2:C2");
  var values = source.getValues();
  values[0][0] = new Date();
  sheet.appendRow(values[0]);
  var cells = sheet.getRange("A2:A980");
  cells.setNumberFormat("dd/MM/yyyy");
};

它从另一个工作表中获取数据并将其附加到 A、B、C 列(日期、金额、%)。 D-G 列包含跟踪 B 和 C 随时间变化的绝对值和百分比变化的公式。目前我每天都去手动复制那些公式,但必须有一种方法可以自动化吗?大概可能的方法包括:

1) 在脚本中添加一些内容以复制前一天的公式。这个人写了一些可能有帮助的东西,但我对编码知之甚少,我什至无法理解如何将其集成到我目前的脚本中:http://googlescripts.harryonline.net/copy-formulas-down

2) 编辑脚本以附加到 A-C 列,忽略其他列中的任何内容。然后我可以填写 D-G 中的公式(使用 IF(isblank...))并将它们留在那里。但是,如果我现在这样做,脚本会在 D-G 列中的所有内容之后将新数据附加到最底部的新行中。

3) 编辑脚本并使用数组公式?我终于制定了一个可以根据自己的条件工作的数组公式。但遗憾的是,该脚本仍然像上面的问题 2 一样运行。即,它将新数据附加到电子表格最底部的新行中,感知所有现有行将由数组公式填充,即使它们返回的是空白单元格。

任何关于如何实现上述任何一项的想法,或任何完全不同的解决方案,都非常感谢!干杯

【问题讨论】:

    标签: javascript google-sheets spreadsheet


    【解决方案1】:

    我的理解是这样的。

    您希望将从另一张工作表中获得的值粘贴到 A 列的第一个空行上(因为如果 A 有值,那么 B 和 C 也有值)。这也应该每天自动完成一次。

    function getFirstEmptyRow() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('History');
      var values = sheet.getRange('A:A').getValues();
      var firstEmptyRow = values.filter(String).length +1; // filter out all non-string entries and get its length+1 (first empty row)
    
      return firstEmptyRow
    }
    

    此函数将第一个空行作为 A 列的整数(数字)返回。

    您的新代码应如下所示

    function recordHistory() {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getSheetByName("History");
      var source = sheet.getRange("A2:C2");
      var values = source.getValues();
      values[0][0] = new Date();
      // sheet.appendRow(values[0]);
      var firstEmptyRow = getFirstEmptyRow();
      sheet.getRange(firstEmptyRow, 1, 1, values[0].length).setValues(values);
      var cells = sheet.getRange("A2:A980");
      cells.setNumberFormat("dd/MM/yyyy");
    };
    
    function getFirstEmptyRow() {
      var sheet = SpreadsheetApp.getActiveSheet().getSheetByName('History');
      var values = sheet.getRange('A:A').getValues();
      var firstEmptyRow = values.filter(String).length +1; // filter out all non-string entries and get its length+1 (first empty row)
    
      return firstEmptyRow
    }
    

    对于每天一次的自动问题。

    要通过脚本编辑器中的对话框创建触发器,请按以下步骤操作:

    1. 从脚本编辑器中,选择编辑 > 当前项目的触发器。
    2. 单击显示:未设置触发器的链接。点击此处立即添加。
    3. 在运行下,选择要触发的函数名称。 (应该是记录历史)
    4. 在事件下,选择时间驱动
    5. 选择每天触发的以及您希望在一天中的哪个时间触发。

    脚本将按照您指定的时间间隔每天自动运行一次您指定的函数。

    脚本将查找 A 列的第一个空行,并将该行的 A、B 和 C 列的值设置为 'values[0]' 中的值。

    这也允许您只用您想要的任何公式填充剩余的列,而不会覆盖它们或将值附加到工作表的底部。

    请注意,尽管我指定的 getFirstEmptyRow 函数(我使用的)速度很快但相当笨拙。例如,它不考虑中间是否有空行。这将使它覆盖最后一个条目(如果只有一个间隙)。

    如果 A 列中总是有一个值,那么这不是问题,如果有差距,请使用下面的代码。

    function recordHistory() {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sheet = ss.getSheetByName("History");
      var source = sheet.getRange("A2:C2");
      var values = source.getValues();
      values[0][0] = new Date();
      // sheet.appendRow(values[0]);
      var firstEmptyRow = getFirstEmptyRow();
      sheet.getRange(firstEmptyRow, 1, 1, values[0].length).setValues(values);
      var cells = sheet.getRange("A2:A980");
      cells.setNumberFormat("dd/MM/yyyy");
    };
    
    function getFirstEmptyRow() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('History');
      var values = sheet.getRange('A:A').getValues();
      var valuesLength = values.length;
      var i;
      var firstEmptyRow;
    
      for (i = 0; i < valuesLength; i++) {
        if (values[i] != '') {
          firstEmptyRow = i +1 // Because index starts from 0 and not 1
        }
      }
    
      return firstEmptyRow + 1 // +1 because the above forloop assigns the last row as the last row containing a value
    }
    

    【讨论】:

    • 您好,感谢您的回复!触发器已经设置好了,这很好。我不完全确定我是否会遇到间隙问题,因为虽然 之间 数据没有任何间隙,但数据仅从 D&E 列的第 4 行开始,F 和第 10 行开始G 的第 33 行(因为 E 是每日变化百分比,F 是每周变化,G 是每月变化)。但是我还不能运行脚本来查看它的行为,因为当我尝试时我得到这个错误:'ReferenceError: "getFirtEmptyRow" is not defined。 (第 8 行,文件“代码”)'。任何想法为什么?
    • 抱歉,已更新响应以在调用函数时不再出现拼写错误。
    • 返回的修订脚本:'TypeError:在对象表中找不到函数 getSheetByName。 (第 15 行,文件“代码”)。一个幸运的猜测似乎解决了它,从 var sheet = SpreadsheetApp.getActiveSheet().getSheetByName('History'); 更改为:var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getSheetByName('History'); 但后来我收到错误:'无法将数组转换为对象 [] []。 (第 9 行,文件“代码”)'
    • 我现在修复了它,当我将二维数组转换为单个数组时尝试应用二维数组中的值时我的错误。
    • 好的,现在可以运行了。但是与原始脚本相同:(新行中的 DG 保持空白。我不愿分享该表,因为它包含财务数据。但找到了解决方法。制作了一份副本,删除了主表,只留下我们正在讨论的 1其中不包含任何敏感信息,只是一堆数字。A2-C2 通常会从另一张表中提取,但我只是出于我们的目的在其中输入了任意数字。希望现在您可以更好地了解发生了什么?Rly感谢您的帮助!docs.google.com/spreadsheets/d/…
    猜你喜欢
    • 1970-01-01
    • 2021-09-06
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多