0

A 列有一个按升序排列的时间戳。G 列有员工姓名。L 列中的每个单元格都有 1、0 或空白。我正在尝试计算每个员工在 L 列中的最新连续 1。我目前的尝试涉及带有以下过滤器的员工姓名列表,“过滤器 L:L,其中 G:G = 员工姓名,L:L 不为空”。我的想法是将此过滤器嵌套在一个自定义公式中,该公式遍历过滤的结果,计算连续 1 并在第一个 0 处停止,返回一个计数。由于时间戳是按升序排列的,我需要它从最后一行向上迭代(或者弄清楚如何更改我的数据导入以附加到工作表的顶部而不是底部)。我的编程经验很少,但这是我失败的尝试。我离我有多远?(顺便说一句,我才意识到我需要它从下往上迭代):

function streak() { 
  var sheet = SpreadsheetApp.getActiveSheet() 
  var range = sheet.getActiveRange(); 
  var cell = sheet.getActiveCell(); 
  var value = cell.getValue();


  for (i in range) { 
    var count = 0 
    if (value = 1) { 
      count += 1; 
      } <br>
    return count; 
} <br>
} <br>
4

1 回答 1

0

你有点接近,但取决于你想要做什么,这最终可能会非常复杂。尽管如此,你在正确的轨道上。

您首先要做的是获取电子表格上活动范围的

var myDataVals = SpreadsheetApp.getActiveSheet().getActiveRange().getValues();

这将为 分配一个二维数组myDataVals

从这里您可以循环遍历外部数组(逐行),然后是每个内部数组(逐列)。有很多方法可以解决这个问题,这实际上取决于你想要做什么。您可以在此处了解有关基本 JavaScript 编程的更多信息:https ://www.javascript.com/resources

我编写了一个示例函数,您可以使用它。我的解决方案是遍历行(外部数组),然后将它们分配给一个对象,其中键是员工姓名;这有效地按名称对行进行排序。然后我按时间戳值按降序对每个名称中的行进行排序。然后,从第一个(最近的)时间戳开始,我检查列 L 是 1 还是 0。如果找到 1,我将 strreaks 对象中名称的键处的数字加 1。如果我找到一个 0,则条纹被打破,我通过将我的 streakEnded 布尔值更改为 true 来退出 while 循环。如果单元格为空白或值不是 1 或 0,则不执行任何操作并继续循环,直到停止或不再有剩余行。

最后,返回 streaks 对象。从那里您可以在工作表中创建一个新页面,或者通过电子邮件发送结果,或者您可能想要做的任何其他事情。现在,我只是将对象记录到脚本记录器中。您可以通过在脚本编辑器中选择(查看 > 日志)来查看结果。确保您已突出显示单元格范围!

function streak() {
  var activeRangeVals, allStreaks, columns;

  // Get the active range as a 2-dimensional array of values
  activeRangeVals = SpreadsheetApp.getActiveSheet().getActiveRange().getValues();

  // Define which columns contain what data in the active Range
  // There are better ways to do this (named ranges)
  // but this was quickest for me.
  columns = {
    'name': 6,      // G
    'streak': 11,   // L
    'time': 0       // A
  };

  allStreaks = getStreaks(getEmployeeRowsObject(activeRangeVals));

  Logger.log(allStreaks);

  return allStreaks;

  function getEmployeeRowsObject(data) {
    // Create an empty object to hold employee data
    var activeName, activeRow, employees = {}, i = 0;

    // Iterate through the data by row and assign rows to employee object
    // using employee names as the key
    for(i = 0; i < data.length; i+= 1) {
      // Assign the active row by copying from the array
      activeRow = data[i].slice();

      // Assign the active name based on info provided in the columns object
      activeName = activeRow[columns['name']];

      // If the employee is already defined on the object
      if(employees[activeName] !== undefined) {
        // Add the row to the stack
        employees[activeName].push(activeRow);

      // If not:  
      } else {
        // Define a new array with the first row being the active row
        employees[activeName] = [activeRow];
      }
    }

    return employees;
  }

  function getStreaks(employees) {
    var activeRow, activeStreak, i = 0, streaks = {}, streakEnded;

    for(employee in employees) {
      activeRow = employees[employee];

      // Sort by timestamp in descending order (most recent first)
      activeRow = activeRow.sort(function(a, b) {
        return b[columns['time']].getTime() - a[columns['time']].getTime();
      });

      i = 0, streaks[employee] = 0, streakEnded = false;

      while(i < activeRow.length && streakEnded === false) {
        activeStreak = parseInt(activeRow[i][columns['streak']]);
        if(activeStreak === 1) {
          streaks[employee] += 1;
        } else if(activeStreak === 0) {
          streakEnded = true;
        }
        i += 1;
      }
    }

    return streaks;
  }

}
于 2016-01-14T21:36:11.747 回答