Google电子表格脚本检查已编辑的单元格是否在特定范围内

时间:2012-09-25 12:42:25

标签: google-apps-script google-sheets

我需要检测是否在某个数据范围内对电子表格进行了更改,如果是,请设置当前更新时间。

问题是,我有一个电子表格,我编辑标题和文本,我不希望在电子表格中更新特定单元格中的更新时间,但当我编辑一系列单元格中的数据时,我想要更新时间变了。

这是我必须更新的时间。

function onEdit(e) 
{
  var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();

  ss.getRange("G10").setValue(new Date());
} ​

如果我编辑某些单元格(在“B4:J6”范围内),我只想要G10中的日期

6 个答案:

答案 0 :(得分:19)

onEdit()函数提供Event作为参数,它包含有关编辑内容的必要信息。如果你想知道(e)到底是什么,那就是它。

由于每次编辑都会调用onEdit()函数,因此您应该尽可能少地进行处理,以确定是否退出。通过使用传入的事件,您将需要更少的服务调用,因此将更有效。如果您需要灵活,Rasmus回答将A1表示法转换为列和行号的方式很好,但如果编辑范围是固定的,您可以简单地使用常数值进行比较 - 再次,减少所需的处理时间。

function onEdit(e) 
{
  var editRange = { // B4:J6
    top : 4,
    bottom : 6,
    left : 2,
    right : 10
  };

  // Exit if we're out of range
  var thisRow = e.range.getRow();
  if (thisRow < editRange.top || thisRow > editRange.bottom) return;

  var thisCol = e.range.getColumn();
  if (thisCol < editRange.left || thisCol > editRange.right) return;

  // We're in range; timestamp the edit
  var ss = e.range.getSheet();
  ss.getRange(thisRow,7)   // "G" is column 7
    .setValue(new Date()); // Set time of edit in "G"
} ​

答案 1 :(得分:4)

最简单的方法是命名您的触发范围

通过命名“触发器”范围,一旦在脚本中设置范围名称,就不必乱用脚本。只需在标准Google工作表界面中编辑命名范围的范围,即使您扩展或缩小范围的大小,脚本仍然可以正常工作。

第1步:命名范围

如果您按照此处的说明编辑范围内的任何单元格,请将您感兴趣的单元格范围命名为脚本的触发器:https://support.google.com/docs/answer/63175

我将我的范围命名为“triggerRange”。

步骤2:将您的范围名称编辑为以下脚本:

function onEdit(e) {
      var myRange = SpreadsheetApp.getActiveSheet().getRange('triggerRange'); //<<< Change Your Named Ranged Name Here inside the getRange() function.
      //SpreadsheetApp.getUi().alert("myRange in A1 Notation is: " + myRange.getA1Notation()); //If you're having problems, uncomment this to make sure your named range is properly defined

      //Let's get the row & column indexes of the active cell
      var row = e.range.getRow();
      var col = e.range.getColumn();
      //SpreadsheetApp.getUi().alert('The Active Cell Row is ' + row + ' and the Column is ' + col); //uncomment this out to do testing

      //Check that your active cell is within your named range
      if (col >= myRange.getColumn() && col <= myRange.getLastColumn() && row >= myRange.getRow() && row <= myRange.getLastRow()) { //As defined by your Named Range
        SpreadsheetApp.getUi().alert('You Edited a Cell INSIDE the Range!');//Repalace Your Custom Code Here
      } else {
        SpreadsheetApp.getUi().alert('You Edited a Cell OUTSIDE the Range!');//Comment this out or insert code if you want to do something if the edited cells AREN'T inside your named range
        return;
      }
    }

PS:感谢其他海报为这个基本脚本提供基本框架。我很明显地对脚本进行了大量评论,因此您可以轻松地对其进行测试。删除我在脚本中创建的警报,以获得更整洁的外观......或者只是复制并粘贴它:

function onEdit(e) {
  var myRange = SpreadsheetApp.getActiveSheet().getRange('triggerRange'); //<<< Change Your Named Ranged Name Here

  //Let's get the row & column indexes of the active cell
  var row = e.range.getRow();
  var col = e.range.getColumn();

  //Check that your active cell is within your named range
  if (col >= myRange.getColumn() && col <= myRange.getLastColumn() && row >= myRange.getRow() && row <= myRange.getLastRow()) { //As defined by your Named Range
    SpreadsheetApp.getUi().alert('You Edited a Cell INSIDE the Range!');//Repalace Your Custom Code Here
  }
}

答案 2 :(得分:3)

您只需检查编辑事件是否在范围内发生。

function onEdit(e)
{
  var sheet = SpreadsheetApp.getActiveSheet();
  var editRange = sheet.getActiveRange();
  var editRow = editRange.getRow();
  var editCol = editRange.getColumn();
  var range = sheet.getRange("B4:J6");
  var rangeRowStart = range.getRow();
  var rangeRowEnd = rangeRowStart + range.getHeight();
  var rangeColStart = range.getColumn();
  var rangeColEnd = rangeColStart + range.getWidth();
  if (editRow >= rangeRowStart && editRow <= rangeRowEnd 
      && editCol >= rangeColStart && editCol <= rangeColEnd)
  {
    // Do your magic here
  }
}

我承认这非常冗长,但我还没有在范围ala range.contains(范围)上找到一个简单的方法

答案 3 :(得分:2)

快速解决Rasmus先前回答的可能问题:

在线:

9
10
0
1
2
3
4
5
6
7
8
1.16667
1.16667
1.16667
1.5
1.5
1.5
1.83333
1.83333
1.83333
-0.666667
-0.333333
0
-0.666667
-0.333333
0
-0.666667
-0.333333
0
1
1
0
1
1
0
1
1
0
0
1
2
3
4
5
6
7
8
9
0
0
1
1
3
3
4
4
6
7
1
3
2
4
4
6
5
7
7
8
0.0610206
0.0606029
0.0601841
0.0612494
0.0593242
0.0589063
0.0599607
0.0595583
0.0591209
0.0601974
0.333333
0.333333
0.333333
0.333333
0.333333
0.333333
0.333333
0.333333
0.333333
0.333333
1
1
1
1
1
1
1
1
1
1

它正在添加(实际上它没有减去初始行和列。这导致比1行和1整列所期望的更大的范围。只需在同一行中减去1:

var rangeRowEnd = rangeRowStart + range.getHeight();
var rangeColEnd = rangeColStart + range.getWidth();

Rasmus Fuglsnag编码,修正应如下所示:

var rangeRowEnd = rangeRowStart + range.getHeight()-1;
var rangeColEnd = rangeColStart + range.getWidth()-1;

感谢 Rasmus Fuglsnag 提供最简单的方法。我无法相信有一种更简单的方法可以通过代码实现这一点。

答案 4 :(得分:2)

如果您只想要几行代码,可以使用:

function onEdit(){
  var cell = SpreadsheetApp.getActive().getActiveCell();
  var row = cell.getRow();
  var col = cell.getColumn();

  //if col > A && col < K ...
  if(col > 1 && col < 11 && row > 3 && row < 7){ //B4:J6
    //do something
  }

但是,更改范围可能需要比其他方法更长的时间。

答案 5 :(得分:0)

要保留舒适的代码,可以使用调度程序(受Doomd的启发)。

/** 
 if the changed cell is in the good sheet and range:
 @returns {Range} : the changed cell range
 else
 @returns {boolean} : false
*/
function onEdit_inRange(e,sheetName,sheetRange){
    var sh=e.range.getSheet();
    if(sh.getName()===sheetName){
        var range = SpreadsheetApp.getActiveSheet().getRange(sheetRange);
        var xy=[e.range.getColumn(),e.range.getRow()];
        if (xy[0]>=range.getColumn() && xy[0]<=range.getLastColumn() && xy[1]>=range.getRow() && xy[1]<=range.getLastRow()) {
            return e.range;
        }
    }
    return false;
}

使用方法:

function onEdit(e){
    var range=0;
    if((range=onEdit_inRange(e,'Stats','Q47:Z47'))){
        _handle_stats(range);
    }else if ((range=onEdit_inRange(e,'Calendar','A5:B29'))) {
        _handle_calendar(range);
    }// etc ...
}