【问题标题】:Google Scripts how to delete extra rows from an array谷歌脚本如何从数组中删除多余的行
【发布时间】:2021-02-19 20:55:21
【问题描述】:

我正在开发一个谷歌表格模板,该模板将内置一些名册维护。当名册在主“名册”选项卡上更新时,我希望工作表中的所有其他选项卡检查学生 ID #s更新的名册标签。在代码中,一个示例工作表是“anet”工作表。我正在使用 indexOf 和 for 循环来检查“anet”表中的每个值与“名册”表中的 ID。如果 ID# 已从“名册”表中删除,我希望在“anet”表中删除该行。

当我现在运行脚本时,一些行被删除了,但不是全部。 ID 列表从“roster”选项卡上的 A3 开始,另一个列表从“anet”选项卡上的 A15 开始。有人可以帮我理解为什么它会删除一些返回 indexOf 为 -1 的行,而不是我需要删除的所有行吗?

function withdrawnStudent (){
  let lastRowTyler = roster.getLastRow();
  let tylerData = roster.getRange(3,1,lastRowTyler,1).getValues();
  let tylerArray = tylerData.map(function(r){ return r[0]});

  
  let anetLastRow = anet.getLastRow();
  
 
  let anetLastColumn = anet.getLastColumn();
  let anetData = anet.getRange(15,1,anetLastRow,anetLastColumn).getValues();
  let anetIDArray = anetData.map(function(r){ return r[0]});'''

  

  for (let index = 14; index < 200; index++){
  
    if(tylerArray.indexOf(anetIDArray[index][0]) === -1){
       anet.deleteRow(index +14);
      
     Logger.log(tylerArray.indexOf(anetIDArray[index][0]))

这是一个示例电子表格的链接。在“名册”选项卡中,它列出了四年级学生 ID。在“anet”选项卡中,应删除所有带数字的行,因为这些是 5 年级 ID。然而,并不是所有的行都会被删除,只有一些。

https://docs.google.com/spreadsheets/d/1vDse6X6gs3bkgnlBfgo-vzERkAMud3rUDC6j8fEkcrk/edit#gid=447751616

【问题讨论】:

  • 我们可以看看一些示例数据吗?
  • 这里是一个示例电子表格的链接。在“名册”选项卡中,它列出了四年级学生 ID。在“anet”选项卡中,应删除所有带数字的行,因为这些是 5 年级 ID。然而,并不是所有的行都会被删除,只有一些。
  • 好吧,看起来你的表在两张表中是相同的,所以为什么你不能每次用户进行更改时用花名册中的表覆盖 anet 中的表,而不是试图找出哪些被删除循环遍历并手动删除?
  • @DaMahdi03 感谢您的回复!我是 javascript 的新手。这实际上是我编码的第一件事。我不能按照你的建议去做,因为随着学年的进行,学生将有评估数据输入。如果名称已在另一个选项卡中过滤/排序,我不希望它们被覆盖。学生的相关评估数据将被混淆。

标签: javascript arrays google-apps-script google-sheets


【解决方案1】:

因此,当文档发生更改时,请设置触发器来触发您的脚本,您的脚本将遍历第一张工作表中的所有可用 ID,并将它们保存到一个数组中。然后在第二张表中,您将遍历 ID,如果它不在数组中,则删除该行。我们要确保我们向后运行循环,因为如果我们删除行并继续向下移动,由于表格向上移动,图表将在这里和那里跳过行。

这是我能想到的:

function withdrawStudent() {
    //Get Student IDs From Roster Spreadsheet
    var rosterSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Roster");
    var dataRangeOnRosterSheet = rosterSheet.getDataRange();
    //Returns a nested Array of all values in the 3rd row, 1st column, all the rows to the end, only one column
    //I added the flat() to make it into a one-dimenstional array
    var studentIDs = rosterSheet.getRange(3, 1, dataRangeOnRosterSheet.getLastRow() - 1, 1).getValues().flat(); 
    Logger.log(JSON.stringify(studentIDs)); //If you want to see what the data looks like
    

    //Now loop through each student ID in the second sheet, and if it doesn't exist in our first array then delete the row
    var ANetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ANet");
    var dataRangeOnANetSheet = ANetSheet.getDataRange();
    var lastRow = dataRangeOnANetSheet.getLastRow();
    var firstRow = 15;
    //Reverse the for loop to work bottom-up because row deletion shifts the chart
    for (var i = lastRow; i >= firstRow; i--) {
        var currentStudentID = ANetSheet.getRange(i, 1, 1, 1).getValue(); //Get Student ID of current row
        //If the currentStudentID is not found in our list of student IDs, remove it
        if (!studentIDs.includes(currentStudentID)) {
            //Remove the row
            ANetSheet.deleteRow(i);
        }
    }

}

如何设置您的触发器,以便每次用户编辑图表时它都会运行您的函数:

免责声明:我复制了您的文档,以便测试我的代码并确保它有效,但我现在要删除它。希望你没事!

【讨论】:

  • 那是我的问题!我需要从底部运行循环!你真是个天才!!
  • 如果是正确的答案,你可以标记它吗?
  • 谢谢!您制作了该文件的副本完全没问题。我感谢您的帮助。奇怪的是,当我运行你的代码时,当我之前使用 indexOf 方法时,当我运行脚本时会保留一些行。为了测试它,我放了一个列表,其中没有一个值在两张纸上匹配。如果脚本正常工作,我相信应该删除 anet 表上所有填充的行,因为在名册表上找不到任何 ID。但是,还剩 14 行。
  • 我通过调用 withdrawStudent() 直接在您的电子表格上运行了我在这里编写的代码,它删除了您所有的五年级 ID
  • 我尝试重新输入您的代码,但我一定是出错了。当我复制/粘贴时,它起作用了!谢谢!!!
猜你喜欢
  • 2022-01-27
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多