【问题标题】:Google Apps Script: how to copy paste ranges based on formulas?Google Apps 脚本:如何根据公式复制粘贴范围?
【发布时间】:2017-12-14 11:10:04
【问题描述】:

我在 Google 表格中有一个模型,该模型设置为每天一列。它包含实际值和预测值,每天我都需要前滚公式以用实际值替换预测值。我不能前滚整列,只能前滚一部分(上面和下面的参考数字不应更改)。

我每天都尝试编写一个脚本来为我执行此操作,但我不知道如何让getRange 引用动态范围。这是我的尝试:

function rollColumn() {
  var ss2 = SpreadsheetApp.openById('<ID redacted>');
  ss2.getRange("=index(Model!$7:$7,,match(today()-2,Model!$4:$4,0)):index(Model!$168:$168,,match(today()-2,Model!$4:$4,0))").copyTo(ss2.getRange("=index(Model!$7:$7,,match(today()-1,Model!$4:$4,0)):index(Model!$168:$168,,match(today()-1,Model!$4:$4,0))"))
};

INDEX 公式在引用相关范围时起作用(我已在电子表格中对其进行了测试)。但显然getRange 不接受公式作为输入。谷歌表格似乎也不允许使用公式创建命名范围(这就是我在 Excel 中解决这个问题的方法)。

有人可以帮我用 GAS 重新创建这个功能吗?

这是我在 Stack Overflow 上找到的最接近的现有问题,但我无法让它发挥作用: Google Apps Script performing Index & Match function between two separate Google Sheets

谢谢!

【问题讨论】:

  • 不清楚您是否尝试过使用日志,或者您是否了解 JavaScript。现在,您的代码的主要问题是您正试图让 Google 表格公式在脚本中工作。但是,Google 表格公式仅在使用 Google 表格编写时才有效。请发送指向其中包含索引匹配的示例 Google 表格的链接。然后我将提供帮助并提供复制其行为的代码。
  • 感谢 Antoine 的快速回复。这是一个简化的样本表:docs.google.com/spreadsheets/d/… 重点是,一旦前一天的数据进来,在这种情况下,我需要将M4:M6 复制到N4:N6 我已经包含了一个黄色的公式,它显示了我将如何得到根据今天的日期到那个范围,但我确信脚本解决方案最终可能会完全不同..再次感谢!
  • 感谢链接,但我看不到公式。你能把分享设置改成public on the web吗?这样每个看到您的问题的人都能看到?
  • 谢谢 Antoine,我已授予您编辑权限,可以回复任何进一步的请求。任何人都应该可以通过链接查看工作表。

标签: google-apps-script google-sheets


【解决方案1】:

您应该在代码中添加 {contentsOnly:false} 参数。像这样:

TemplateSheet.getRange("S2:T2").copyTo(DestSheet.getRange("S2:T"+LRow2+""), {contentsOnly:false});

【讨论】:

    【解决方案2】:

    从列标题中获取日期,然后将公式粘贴到右侧的行:

    // note: we assume that sheet is disposed as in the following document: https://docs.google.com/spreadsheets/d/1BU2rhAZGOLYgzgSAdEz4fJkxEcPRpwl_TZ1SR5F0y08/edit?ts=5a32fcc5#gid=0
    function find_3formulas() {
    
      var sheet = SpreadsheetApp.getActiveSheet(),
          leftTitle, // this variable will stay unused because we do not need a vertical index
          topTitle = todayMinus_xDays(2),
          topTitlesRange = sheet.getRange("G3:T3"),
          leftTitlesRange = sheet.getRange("A4:A8"); // this range will stay unused.
    
      var coor = findCoordinates(leftTitlesRange, leftTitle, topTitlesRange, topTitle);
    
      if (coor.row == null || coor.column == null) {
        sheet.getRange("M12:M14").setFormula('="NULL: please check logs"'); 
        return;
      }
    
      var rowAxis = 4 + coor.row;
      var colAxis = 8 + coor.column;
      var fromRange = sheet.getRange(rowAxis, colAxis, 3, 1);
      var toRange = sheet.getRange(rowAxis, colAxis + 1, 3, 1);
    
      Logger.log(fromRange.getA1Notation())
      Logger.log(toRange.getA1Notation());
    
      var threeFormulas = fromRange.getFormulas();
    
      toRange.setFormulas(threeFormulas)
    }
    
    // unused in current script!
    function findCoordinates(leftTitlesRange, leftTitle, topTitlesRange, topTitle) {
    
      var formattedDate, 
          row = 0, 
          column = 0;
    
      if (leftTitle) {
        row = findRow(leftTitlesRange, leftTitle);
      }
    
      if (topTitle) {
        column = findColumn(topTitlesRange, topTitle);
      }
    
      var array = {row:row, column:column}
    
      return array;
    }
    
    // unused in current script!
    function findRow(range, valueToSearch) {
    
      var colRows = range.getValues();
      for (i = 0; i < colRows.length; i++) {
        if (valueToSearch == colRows[i][0]) {return i;}
      } 
      // however, if found nothing: 
      Logger.log("the value " + valueToSearch + " could not be found in row titles");
      return null;
    }
    
    // assumes that column titles are dates, therefore of type object.
    function findColumn(range, valueToSearch) {
    
      var colTitles = range.getValues();
      for (i = 0; i < colTitles[0].length; i++) { 
        if (typeof colTitles[0][i] == "object") {
          formattedDate = Utilities.formatDate(colTitles[0][i], "GMT", "yyyy-MM-dd")
        };
        if (valueToSearch === formattedDate) {return i;}
      }
      // however, if found nothing:
      Logger.log("today's date, " + valueToSearch + ", could not be found in column titles");
      return null;
    }
    
    // substracts 2 days from today, then returns the result in string format.
    function todayMinus_xDays(x) {
      var d = new Date();
      d = new Date(d - x * 24 * 60 * 60 * 1000);
      d = Utilities.formatDate(d, "GMT", "yyyy-MM-dd");
      return d;
    }
    

    【讨论】:

    • 非常感谢您的帮助!不幸的是,我不认为这个脚本完全符合我的想法,因为我需要粘贴公式而不是值,而且我不能 100% 确定如何修改它。在自然语言术语中,我需要一个脚本来执行以下操作: a) 在 $4:$8 区域内,找到在今天减去 2 天后匹配的列(使用 $3:$3)。 b) 将此范围(当前为 N4:N8)复制到沿 (O4:O8) 的一列,保留公式和格式。这很容易解决吗?
    • 好的,现在代码完成了所有这些。让我知道它是否适合您
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多