【问题标题】:Add a row and sort the sheet (Google Apps Script)添加一行并对工作表进行排序(Google Apps 脚本)
【发布时间】:2021-09-07 15:44:46
【问题描述】:

我正在编写一个脚本来将学生分成干预组,并且我希望结果表按字母顺序排序。我还需要在要添加的新行中添加复选框。我的代码有效,但它似乎非常低效,因为我添加了带有复选框的新行,获取新数据范围,对其进行排序,然后将其重写到电子表格中。任何清理它的帮助将不胜感激。

function filterToGroup(sheet, student, value) {
  var oldDataRange = sheet.getDataRange();
  var oldDataValues = oldDataRange.getValues();

  if (value === true) {
    // Add new row to spreadsheet based on filter requirements
    sheet.appendRow([student]);
    // Insert checkboxes after the name to complete the row
    sheet.getRange(sheet.getLastRow(), 2, 1, oldDataValues[0].length).insertCheckboxes();
    // Get the sheet values with the new row
    var newRange = sheet.getRange(2, 1, sheet.getLastRow() -1, oldDataValues[0].length);
    var newValues = newRange.getValues();
    // Sort them
    var sortedNewValues = newValues.sort(function(a,b) {return a[0] > b[0] ? 1 : -1});
    // Write the newly sorted values back to the sheet
    newRange.setValues(sortedNewValues);
  } else {
    for (i = 1; i < oldDataValues.length; i++) {
      if (student == oldDataValues[i][0]) {
        sheet.deleteRows(i+1, 1);
        break;
      }
    }
  }

当老师点击“Phonics”下的复选框时,我希望学生添加到带有复选框的“Phonics”表中:

启动filterToGroup函数的函数是

function onEdit(e) {
  var editedSheet = e.range.getSheet().getSheetName();
  var editedColumn = e.range.getA1Notation().charAt(0);
  var editedValue = e.range.getValue();
  var student = rosterValues[e.range.getRow() -1][0];
  if (editedSheet == "Roster") {
    if (editedColumn == "E") filterToGroup(phonicsSheet, student, editedValue);
    if (editedColumn == "G") filterToGroup(phonologicalAwarenessSheet, student, editedValue);
    if (editedColumn == "H") filterToGroup(letterNamesAndSoundsSheet, student, editedValue);
  }
}

我想我已经弄清楚了。它仍然不是超级快,但它不到一秒钟并且不会两次写入工作表。一旦我发现我可以在事后插入复选框,它真的很有帮助。这是新代码:

function filterToGroup(sheet, student, value) {
  var oldDataRange = sheet.getDataRange();
  var oldDataValues = oldDataRange.getValues();

  if (value === true) {
    // Check if the student is the first to be added;
    // If so, just append row
    if (oldDataValues.length === 1) {
      phonicsSheet.appendRow([student]);
      // Run the new addCheckboxes function to add checkboxes to row
      addCheckboxes(phonicsSheet, 1, oldDataValues[0].length -1);
    } else {
      // If data has already been added, remove header row
      oldDataValues.shift();
      // Create a new array with the student data and false values
      var newStudent = Array.apply(null, Array(oldDataValues[0].length -1).map(_ => false));
      newStudent.unshift(student);
      // Add the new student to the data and sort
      oldDataValues.push(newStudent);
      var newDataValues = oldDataValues.sort();
      // Write the sorted object to the sheet
      sheet.getRange(2, 1, newDataValues.length, newDataValues[0].length).setValues(newDataValues);
      // Add checkboxes to the sheet (existing true values will still be recognized)
      addCheckboxes(sheet, newDataValues.length, newDataValues[0].length -1);
    }
  } else {
    for (i = 1; i < oldDataValues.length; i++) {
      if (student == oldDataValues[i][0]) {
        sheet.deleteRows(i+1, 1);
        break;
      }
    }
  }
}

function addCheckboxes(sheet, numRows, numCols) {
  sheet.getRange(2, 2, numRows, numCols).insertCheckboxes();
}

【问题讨论】:

  • 我假设您在循环中调用 filterToGroup。如果这样做,那肯定会非常低效。我的建议是读取所有值,添加行,进行更改并将所有内容写回工作表。最终,您将进行一次读取和一次写入操作。要以这种方式添加复选框,您需要联系工作表服务/API 并在调用 developers.google.com/sheets/api/reference/rest/v4/spreadsheets/… 之前准备一批
  • 它不是循环的一部分。它在单击复选框时触发。如果该框为真,它会将学生发送到新工作表并按字母顺序对其进行排序。如果为假,则删除学生所在的行。是复选框让我失望。我知道如何仅使用数据来执行此操作,但设置复选框很困难。
  • 我在原始帖子中添加了其他信息。
  • 请同时提供样张,以便更好地把握您的顾虑。

标签: google-apps-script google-sheets


【解决方案1】:

您的代码应该运行良好,但是如果您想删除某些代码行,您可以在执行getValues() 时删除排序行并直接排序。您的新代码应如下所示:

function filterToGroup(sheet, student, value) {
  var oldDataRange = sheet.getDataRange();
  var oldDataValues = oldDataRange.getValues();

  if (value === true) {
    // Add new row to spreadsheet based on filter requirements
    sheet.appendRow([student]);
    // Insert checkboxes after the name to complete the row
    sheet.getRange(sheet.getLastRow(), 2, 1, oldDataValues[0].length).insertCheckboxes();
    // Get the sheet values with the new row
    var newRange = sheet.getRange(2, 1, sheet.getLastRow() -1, oldDataValues[0].length);
    var newValues = newRange.getValues().sort();
    // Write the newly sorted values back to the sheet
    newRange.setValues(newValues);
  } else {
    for (i = 1; i < oldDataValues.length; i++) {
      if (student == oldDataValues[i][0]) {
        sheet.deleteRows(i+1, 1);
        break;
      }
    }

这基本上删除了代码中的 1 行,但仍应以与以前相同的方式运行。

【讨论】:

  • 这仍然会写入工作表两次,这是我试图避免的。我想我明白了。我会发布我的新代码。谢谢!
  • 我明白了。不过,这个问题不在原帖中。不过,很高兴知道您已经找到了解决方案。编码快乐!
  • 抱歉,原文中的表述不清楚。无论如何,感谢您的帮助。
  • 不过,您确实清理了我的代码,我在解决方案中使用了这些建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-08
  • 1970-01-01
  • 2022-09-23
相关资源
最近更新 更多