简体   繁体   English

Google表格根据单元格内容移动光标onEdit触发器

[英]Google Sheets move cursor onEdit trigger based on cell content

I am trying to write a Google Sheets Apps Script function that checks the content of the current active cell, matches it to the content of another cell, then moves the cursor according to the result of that check. 我正在尝试编写Google表格应用程序脚本功能,该功能检查当前活动单元格的内容,将其与另一个单元格的内容进行匹配,然后根据该检查的结果移动光标。

For a spreadsheet as this example one: https://docs.google.com/spreadsheets/d/1kpuVT1ZkK0iOSy_nGNPxvXPTFJrX-0JgNmEev6U--5c/edit#gid=0 对于此示例的电子表格: https//docs.google.com/spreadsheets/d/1kpuVT1ZkK0iOSy_nGNPxvXPTFJrX-0JgNmEev6U--5c/edit#gid=0

I would like the user to go to D2, enter a value followed by Tab, then while the active cell is in E2, the function will check if the value in D2 is the same in B2. 我希望用户转到D2,输入一个值后跟Tab,然后当活动单元格在E2时,该函数将检查D2中D2中的值是否相同。 If it is, stays in E2. 如果是,请留在E2。 Then we enter the value in E2 followed by Tab, the function checks if it's the same as C2, if it is, then moves from F2 down and left twice to D3. 然后我们在E2中输入值,然后输入Tab,函数检查它是否与C2相同,如果是,则从F2向下移动并向左移动两次到D3。 So if all the values are entered correctly, the cursor zig-zags between the cells in D, E and F as shown below: 因此,如果正确输入了所有值,则光标在D,E和F中的单元格之间曲折,如下所示:

在此输入图像描述

The closest I could find is the answer to the one below, but it involves clicking on a method in the menu each time: 我能找到的最接近的是下面的答案,但它涉及每次点击菜单中的方法:

Move sheet rows on based on their value in a given column 根据给定列中的值移动工作表行

I imagine the function could be triggered at the beginning of editing the document, then it keeps moving the cursor until the document is completed, at which point the function can be stopped. 我想这个函数可以在编辑文档开始时触发,然后它继续移动光标直到文档完成,此时函数可以停止。

Any ideas? 有任何想法吗?

EDIT: what I've tried so far: 编辑:到目前为止我尝试过:

I have managed to change the position to a hard-coded position 'D3' and to create a function that moves one down with these functions: 我已设法将位置更改为硬编码位置'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);
  }
}

As I mentioned in my comment, you want to use a simple trigger function (so that it works for all users without requiring them to first authorize the script). 正如我在评论中提到的,您希望使用一个简单的触发器函数(这样它就适用于所有用户,而不需要他们首先授权脚本)。 There are naturally some limitations of simple triggers , but for the workflow you describe, they do not apply. 简单触发器自然存在一些局限性 ,但对于您描述的工作流程,它们并不适用。

A key principle of a function receiving the on edit trigger invocation is that it has an event object with data about the cell(s) that were edited: 接收on edit触发器调用的函数的一个关键原则是它有一个事件对象,其中包含有关已编辑的单元格的数据:

  • authMode : A value from the ScriptApp.AuthMode enum. authModeScriptApp.AuthMode枚举中的值。
  • oldValue : Cell value prior to the edit, if any. oldValue :编辑前的单元格值(如果有)。 Only available if the edited range is a single cell. 仅在编辑范围是单个单元格时可用。 Will be undefined if the cell had no previous content. 如果单元格没有以前的内容,将不确定。
  • range : A Range object, representing the cell or range of cells that were edited. range :一个Range对象,表示已编辑的单元格或单元格区域。
  • source : A Spreadsheet object, representing the Google Sheets file to which the script is bound. source :一个Spreadsheet对象,表示脚本绑定到的Google Sheets文件。
  • triggerUid : ID of trigger that produced this event (installable triggers only). triggerUid :产生此事件的触发器的ID(仅可安装触发器)。
  • user : A User object, representing the active user, if available (depending on a complex set of security restrictions ). user :表示活动用户的User对象(如果可用)(取决于一组复杂的安全限制 )。
  • value : New cell value after the edit. value :编辑后的新单元格值。 Only available if the edited range is a single cell. 仅在编辑范围是单个单元格时可用。

Of these, we will use range and value . 其中,我们将使用rangevalue I will leave the business case of handling edits to multiple-cell ranges to you. 我将把处理编辑的业务案例留给多个单元格范围给你。 Stack Overflow is, after all, not where you obtain turnkey solutions ;) 毕竟,Stack Overflow不是您获得交钥匙解决方案的地方;)

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;
  }
}

As you digest the above, you'll note that you are required to supply certain values that are particular to your own workflow, such as a sheet name, and the proper columns. 在您消化上述内容时,您会注意到您需要提供特定于您自己的工作流程的某些值,例如工作表名称和正确的列。 The above can be modified in a fairly straightforward manner to advance rightward if the edited column is one of several columns, using either a constant offset to the respective "check" column, or an array of respectively-ordered offsets / target columns. 如果编辑的列是若干列之一,则使用对相应“检查”列的常量偏移或分别排序的偏移/目标列的数组,可以以相当简单的方式修改上述内容以向右前进。 (Such a modification would almost certainly require the use of Array#indexOf .) (这样的修改几乎肯定需要使用Array#indexOf 。)

A caveat I note is that strict equality === fails if your edits are numbers representable as integers, because Google Sheets will store the number as a float. 需要注意的是,如果您的编辑数字可以表示为整数,则严格相等===失败,因为Google表格会将数字存储为浮点数。 Strict equality precludes type conversion by definition, and no int can ever be the exact same as a float . 严格的相等性排除了类型转换,并且没有int可以与float完全相同。 Thus, the generic equality == is used. 因此,使用通用等式== The above code will not equate a blank check cell and the result of deleting content. 上述代码不会等同于空白检查单元格和删除内容的结果。

Method references: 方法参考:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM