Google表格会根据单元格内容将光标移至onEdit触发器上

时间:2018-07-20 15:53:34

标签: google-apps-script google-sheets

我试图编写一个Google Sheets Apps脚本函数,以检查当前活动单元格的内容,将其与另一个单元格的内容匹配,然后根据该检查结果移动光标。

以电子表格为例: https://docs.google.com/spreadsheets/d/1kpuVT1ZkK0iOSy_nGNPxvXPTFJrX-0JgNmEev6U--5c/edit#gid=0

我希望用户转到D2,输入一个值,然后按Tab,然后在活动单元格位于E2时,该功能将检查D2中的值是否与B2中的相同。如果是,请停留在E2中。 然后我们在E2中输入值,然后按Tab键,该函数检查它是否与C2相同,如果相同,则从F2向下移动两次,并两次移至D3。因此,如果正确输入所有值,则光标将在D,E和F中的单元格之间作曲折,如下所示:

enter image description here

我能找到的最接近的答案是下面的答案,但这每次都涉及在菜单中单击一种方法:

Move sheet rows on based on their value in a given column

我想该功能可以在编辑文档开始时触发,然后一直移动光标直到文档完成,此时可以停止该功能。

有什么想法吗?

编辑:到目前为止,我已经尝试过:

我设法将位置更改为硬编码位置“ D3”,并创建了一个可以使用以下功能向下移动的功能:

function onOpen() {
  var m = SpreadsheetApp.getUi().createMenu('Move');
  m.addItem('Move to D3', 'move').addToUi();
  m.addItem('Move to one below', 'move2').addToUi();
  m.addItem('Move down left', 'move_down_left').addToUi();
}

function move() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getActiveSheet();
  var range = s.getRange('D3');
  s.setActiveRange(range);  
}

function move2() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getActiveSheet();
  var r = s.getActiveRange();
  var c = r.getCell(1,1);
  var target = s.getRange(c.getRow() + 1, c.getColumn());
  s.setActiveRange(target);
}

function move_down_left() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getActiveSheet();
  var r = s.getActiveRange();
  var c0 = r.getCell(1,1);
  var r1 = s.getRange(c0.getRow(), c0.getColumn() - 1);
  var c1 = r1.getCell(1,1);
  var r2 = s.getRange(c1.getRow(), c1.getColumn() - 2);
  var c2 = r2.getCell(1,1);
  if (c1.getValue() == c2.getValue()) {
    var target = s.getRange(c1.getRow() + 1, c1.getColumn() - 1);
    s.setActiveRange(target);
  }
}

1 个答案:

答案 0 :(得分:2)

正如我在评论中提到的那样,您想使用simple trigger函数(以便该函数适用于所有用户,而无需他们首先授权该脚本)。自然有一些limitations of simple triggers,但是对于您描述的工作流程,它们并不适用。

接收on edit触发器调用的函数的关键原理是它具有一个event object,其中包含有关已编辑单元格的数据:

  
      
  • authMode :   来自ScriptApp.AuthMode枚举的值。
  •   
  • 旧值:   编辑之前的单元格值(如果有)。仅在编辑范围为单个单元格时可用。如果单元格没有以前的内容,则将是不确定的。
  •   
  • 范围:   Range对象,代表已编辑的单元格或单元格范围。
  •   
  • 来源:   Spreadsheet对象,代表脚本绑定到的Google表格文件。
  •   
  • triggerUid :   产生此事件的触发器的ID(仅适用于可安装的触发器)。
  •   
  • 用户:   一个User对象,代表活动用户(如果有)(取决于security restrictions的复杂集合)。
  •   
  • :   编辑后的新单元格值。仅在编辑范围为单个单元格时可用。
  •   

其中,我们将使用rangevalue。我将把处理对多个单元格范围的编辑的业务案例留给您。毕竟,堆栈溢出不是您获得统包解决方案的地方;)

function onEdit(e) {
  if (!e) throw new Error("You ran this from the script editor");
  const edited = e.range;
  if (edited.getNumRows() > 1 || edited.getNumColumns() > 1)
    return; // multicell edit logic not included.

  const sheet = edited.getSheet();
  if (sheet.getName() !== "your workflow sheet name")
    return;

  // If the user edited a specific column, check if the value matches that
  // in a different, specific column.
  const col = edited.getColumn(),
      advanceRightColumn = 5,
      rightwardsCheckColumn = 2;
  if (col === advanceRightColumn) {
    var checkedValue = edited.offset(0, rightwardsCheckColumn - col, 1, 1).getValue();
    if (checkedValue == e.value) // Strict equality may fail for numbers due to float vs int
      edited.offset(0, 1, 1, 1).activate();
    else
      edited.activate();
    return;
  }

  const endOfEntryColumn = 8,
      endCheckColumn = 3,
      startOfEntryColumn = 4;
  if (col === endOfEntryColumn) {
    var checkedValue = edited.offset(0, endCheckColumn - col, 1, 1).getValue();
    if (checkedValue == e.value)
      edited.offset(1, startOfEntryColumn - col, 1, 1).activate();
    else
      edited.activate();
    return;
  }
}

在消化上面的内容时,您会注意到需要提供某些特定于您自己的工作流的值,例如工作表名称和适当的列。如果被编辑的列是多个列之一,则可以以相当简单的方式修改以上内容,以使用相应“ check”列的恒定偏移量或分别排列的偏移量/目标列的数组向右移动。 (这样的修改几乎可以肯定需要使用Array#indexOf。)

我要注意的一点是,如果您的编辑是可表示为整数的数字,则严格相等===会失败,因为Google表格会将数字存储为浮点数。严格的相等性会按定义排除类型转换,并且任何int都不能与float完全相同。因此,使用泛型相等性==。上面的代码不会等同于空白的检查单元格和删除内容的结果。

方法参考: