【问题标题】:Dynamically edit columns in google sheets动态编辑谷歌表格中的列
【发布时间】:2021-01-14 10:10:37
【问题描述】:

上下文

我正在创建一个股票价格数据数据库。我目前正在使用下面的onEdit 函数:

function onEdit(e) {
  // Get the spreadsheet that this will apply to, the tabs and columns
  var ss = e.source.getActiveSheet();
  var excludeTabs = ["Summary", "FTSE 250"];
  var excludeColumns = [1,2,12,13,14,15,16]; // the columns to isolate for special reasons
  var excludeCells = ["M1","I1","I2"];
  // What is the criteria for action to be taken? If the terms defined in excludeTabs are met, then move onto the next criteria (indexOf used because we stored it as an array
  if(excludeTabs.indexOf(ss.getName())===-1){
    // The range from the spreadsheet. 
    // Scripts expects an event in a cell
    var cell = e.range;
    // For the entire column of this cell
    var col = cell.getColumn();
    // Within the universe of tabs that this script applies to, we want to exclude the columns in the array
    if(excludeColumns.indexOf(col)===-1)
      // Within the universe of tabs and columns, we want to exclude certain cells
      if(excludeCells.indexOf(cell)===-1)
      // Need to make sure it only applies to formulas
        if(cell.getFormula() !== ""){ 
          var destination = ss.getRange(4, col, ss.getLastRow()-1, 1); 
          cell.copyTo(destination);  
      }//End of the remaining universe of data taking out the exceptions
     }//End Tab criteria
}//End function

这允许在我编辑单元格时对某些列进行编辑。到目前为止,它可以工作,但有一些问题。

问题 1

有时,当我编辑列第四行上方的单元格时,它会编辑整个列,尽管我告诉它从第四行开始。这发生在几分钟前的一个单元格中,我告诉它排除在“I2”之上。我写的代码有什么问题吗?

问题 2 我尝试为代码创建其他异常,对于某些指定的范围,它只会从不同的单元格范围进行编辑。不是每列的第四个单元格,而是第 10 个单元格。我尝试在var destination = ss.getRange(4, col, ss.getLastRow()-1, 1) 下方添加它,但它不起作用。我还尝试为不同的单元格位置创建单独的 onEdit 函数,但它也不起作用。

到目前为止,我一直在使用如下表格公式: IFERROR(IFS(C4="Returns","",AND(C4="",C5="",C6="",C7="",C8=""),"",AND(ISNUMBER(C4),ISNUMBER(C5),ISNUMBER(C6),ISNUMBER(C7),ISNUMBER(C8)),COVAR($C4:$C8,'FTSE 250'!J5:J9)),""))

但这只会变得一团糟。有时单元格中有数据,因此它会使上述公式变得无用。下图就是一个例子。

更新我希望 onEdit 从该列的第 10 行开始并向下拖动,但仅限于该列(这是我将要编辑的该列中的行)。我还希望能够对其他列执行此操作(从不同的行开始自动复制过程)。

  • 这是我要编辑的范围

[

更新 2

...

 if(!excludeTabs.includes(ss.getName()) &&  
     !excludeColumns.includes(col) &&
     !excludeCells.includes(cell.getA1Notation()) &&
     cell.getFormula() !== ""
    ){
      
    if(col==33){
      var destination = ss.getRange(8, col, ss.getMaxRows()-7, 1);
      cell.copyTo(destination);    
    }

   else if(col===30){
          var destination = ss.getRange(8, col, ss.getMaxRows()-7, 1);
          cell.copyTo(destination); 
        }

    else{
    var destination = ss.getRange(4, col, ss.getMaxRows()-3, 1);
    cell.copyTo(destination);    
      }


    }

【问题讨论】:

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


    【解决方案1】:

    解释:

    问题:

    • 您的 if 语句中没有包含代码的右括号。

    • 这里if(excludeCells.indexOf(cell)===-1)有问题:

      var excludeCells = ["M1","I1","I2"]; 是一个字符串数组,var cell = e.range; 是一个范围对象。您实际上是在比较两个不同的事物(string 与 range 对象。)

      您想要替换:if(excludeCells.indexOf(cell)===-1) with if(excludeCells.indexOf(cell.getA1Notation())===-1)。

    改进:

    • 不要使用多个 if 语句,这些语句最后会导致一个单独的代码块,而是使用一个具有多个条件的 if 语句。

    • 这个范围getRange(4, col, ss.getLastRow()-1, 1); 也没有多大意义。使用ss.getLastRow()-3 更有意义,因为您从3 开始。

    • 您可以像 !excludeCells.includes(cell.getA1Notation()) 那样使用 includes(),而不是使用长表达式 excludeCells.indexOf(cell.getA1Notation())===-1。

    解决方案:

    function onEdit(e) {
      var ss = e.source.getActiveSheet();
      var excludeTabs = ["Summary", "FTSE 250"];
      var excludeColumns = [1,2,12,13,14,15,16]; // the columns to isolate for special reasons
      var excludeCells = ["M1","I1","I2"];
      var cell = e.range;
      var col = cell.getColumn();
      
      if(!excludeTabs.includes(ss.getName()) &&  
         !excludeColumns.includes(col) &&
         !excludeCells.includes(cell.getA1Notation()) &&
         cell.getFormula() !== ""
        ){         
          if(col==33){
           var destination = ss.getRange(10, col, ss.getMaxRows()-9, 1);
           cell.copyTo(destination);    
          }
          else{
           var destination = ss.getRange(4, col, ss.getMaxRows()-3, 1);
           cell.copyTo(destination);    
          }
         }
    }
    

    请注意:

    • getLastRow() 返回包含内容的最后一行。例如,如果您有 10 列,第一个 10 的最后一行内容为 55,但在工作表末尾的列 20 中有一个随机值,假设行 900 然后 900将是您工作表中的最后一行。请注意这一点,否则您将需要其他方法来获取最后一行的内容。公式也是内容。因此,一直到工作表底部的公式可能会确定 getLastRow 返回的内容。

    【讨论】:

    • @Desmond 检查我更新的答案。但同样不能 100% 确定您的意思。您想将刚刚编辑的单元格的值/公式复制到从第 10 行一直到您编辑的特定列的工作表底部的一系列单元格中?
    • @Desmond 不,请参阅我的回答。您可以在末尾添加另一个if 条件来检查编辑的列是否为AG,即33 列。让我知道这是否是你想要的。您还想允许对每个单元格或特定行进行编辑吗?例如,仅在将行 1 编辑为 4 或其他内容时运行代码。
    • 您有任何错误吗?转到执行页面并告诉我您是否遇到任何错误。从字面上看,我使用了与以前完全相同的代码,但我只是创建了一个超级简单的if ,用于检查列是否为AG。请发布错误或再次测试。还要提醒您,您已经排除了几列,因此您可能正在测试错误的列。还要确保您的编辑是formula,因为这是条件的一部分。如果它们都不起作用,那么请分享一张模拟表(删除敏感信息),以便我们找到解决方案。这将为我们双方节省大量时间。 @Desmond
    • Dw,它有效。抱歉,我忘记删除部分旧代码,因此无法正常运行。再次感谢!! :D
    • @Desmond 我在您的问题中修复了您的代码,但如果您有后续问题,我建议您创建另一个帖子。您当前的问题、我的回答和评论部分变得非常庞大,未来的读者将不会从这篇文章中受益。感谢并为给您带来的不便深表歉意。
    【解决方案2】:

    试试这个:

    function onEdit(e) {
      var sh = e.range.getSheet();
      var excludeTabs = ["Summary", "FTSE 250"];
      var excludeColumns = [1,2,12,13,14,15,16]; 
      var excludeCells = ["M1","I1","I2"];
      if(excludeTabs.indexOf(sh.getName())==-1 && excludeColumns.indexOf(e.range.columnStart)==-1 && excludeCells.indexOf(e.range.getA1Notation())==-1 && e.range.getFormula()!=""){    
          e.range.copyTo(sh.getRange(4, e.range.columnStart, sh.getLastRow()-3, 1));//The numbers of rows to the bottom is sh.getLastRow()-3 -1 will have to roll off of the bottom of the spreadsheet which will give you out of range errors  
        }
      }
    }
    

    【讨论】:

    • 很抱歉,我没有注意到你在那里。我应该在发布之前刷新页面。我只是拿走了操作员的代码,然后把所有的垃圾都拿出来了。
    • 很好,两者都工作,越多越好。我已经更新了第二个问题。谢谢你们!
    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 2021-01-07
    相关资源
    最近更新 更多