【问题标题】:Making Script Quicker/more efficient使脚本更快/更高效
【发布时间】:2018-03-08 03:37:36
【问题描述】:

我正在尝试让脚本检查 sheet1 的名字和姓氏(2 个单元格),使用 sheet1 中每个人的名字和姓氏,然后在 sheet2 中检查每个人的 4-5 行中的值是否大于0.

问题是某些名称位于不同的列中,我需要检查一列,并根据大型(180 个单元格)名称列表检查该列中的这些名称。这是超时的部分。

我的代码完全正常运行,但它使用了某些部分过多并最终超时。 getvalue 函数被大量使用,我不确定使用它的更好方法。我正在寻找如何让它更高效或运行得更好。

我可能只需要在代码中输入名称以使其更快,但我希望有一种更加用户友好的方法,以便名称可以在 sheet1 中更改并在脚本中自动格式化。

谢谢!

function getvalue(CellName) {
  return SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet2').getRange(CellName).getValues();
}

function getAdvisee(CellName) {
 return SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1').getRange(CellName).getValues(); 
}

function teacher1() {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('sheet1');
  var LastRow = ss.getLastRow();
  var columns = 3;
  var columnassignments = 3;
  var columnEnrichment = 3;
  var columnAmount = 3;
  var advisoryStudent = getvalue('a' + columnEnrichment);
  var studentEnrichment = getvalue('g'+ columnEnrichment);
  var hours = Utilities.formatDate(studentEnrichment, 'EST', 'mm');
  var minutes = Utilities.formatDate(studentEnrichment, 'EST', 'ss');
  var teacherEmail = getAdvisee('b2');
  var student1 = getAdvisee('b3');
  var student1F = getAdvisee('b3');
  var student2 = getAdvisee('b4');
  var student2F = getAdvisee('b4');
  var student3 = getAdvisee('b5');
  var student3F = getAdvisee('b5');
  var student4 = getAdvisee('b6');
  var student4F = getAdvisee('b6');
  var student5 = getAdvisee('b7');
  var student5F = getAdvisee('b7');
  var student6 = getAdvisee('b8');
  var student6F = getAdvisee('b8');
  var student7 = getAdvisee('b9');
  var student7F = getAdvisee('c9');
  var student8 = getAdvisee('b10');
  var student8F = getAdvisee('c10');
  var student9 = getAdvisee('b11');
  var student9F = getAdvisee('c11');
  var student10 = getAdvisee('b12');
  var student10F = getAdvisee('c12');
  var student11 = getAdvisee('b13');
  var student11F = getAdvisee('c13');


  for (columns; columns <= LastRow && columns <= 160; columns++) {
    var advisoryStudent = getvalue('a' + columns);
    var advisoryStudentSp = getvalue('b' + columns);
    var reminderCount = getvalue('e' + columns);
    var reminderLink = getvalue('m'+columns);
    if (advisoryStudentSp == student1F || advisoryStudent == student2 && advisoryStudentSp == student2F || advisoryStudentSp == student3F || advisoryStudentSp == student4F || advisoryStudentSp == student5F || advisoryStudentSp == student6F || advisoryStudentSp == student7F && advisoryStudent == student7 || advisoryStudentSp == student8F || advisoryStudent == student9 && advisoryStudentSp == student9F|| advisoryStudent == student10 && advisoryStudentSp == student10F || advisoryStudent == student11 && advisoryStudentSp == student11F) {
      if ( getvalue('e' + columns) > 0 ) {
        reminders = reminders + getvalue('b' + columns) + ' ' + getvalue('a' + columns) + ': ' + reminderCount + '<br>Reminder Link: ' + reminderLink + '<br>';
      }
    }
  }

  for (columnassignments; columnassignments <= LastRow && columnassignments <= 160; columnassignments++) {
    var advisoryStudent = getvalue('a' + columnassignments);
    var advisoryStudentSp = getvalue('b'+columnassignments);
    var assignmentCount = getvalue ('f' + columnassignments);
    var assignmentLink = getvalue('n' + columnassignments);
    if (advisoryStudentSp == student1F || advisoryStudent == student2 && advisoryStudentSp == student2F || advisoryStudentSp == student3F || advisoryStudentSp == student4F || advisoryStudentSp == student5F || advisoryStudentSp == student6F || advisoryStudentSp == student7F && advisoryStudent == student7 || advisoryStudentSp == student8F || advisoryStudent == student9 && advisoryStudentSp == student9F|| advisoryStudent == student10 && advisoryStudentSp == student10F || advisoryStudent == student11 && advisoryStudentSp == student11F) {
      if (getvalue('f' + columnassignments) > 0) {
        assignments = assignments + getvalue('b' + columnassignments) + ' ' + getvalue('a' + columnassignments) + ': ' + assignmentCount + '<br>Assignment Link: ' + assignmentLink + '<br>';
      }
    }
  }

    for (columnAmount; columnAmount <= LastRow && columnAmount <= 160; columnAmount++) {
      var advisoryStudent = getvalue('a' + columnAmount);
      var advisoryStudentSp = getvalue('b' + columnAmount);
      var amountowed = getvalue ('i' + columnAmount);
      if (advisoryStudentSp == student1F || advisoryStudent == student2 && advisoryStudentSp == student2F || advisoryStudentSp == student3F || advisoryStudentSp == student4F || advisoryStudentSp == student5F || advisoryStudentSp == student6F || advisoryStudentSp == student7F && advisoryStudent == student7 || advisoryStudentSp == student8F || advisoryStudent == student9|| advisoryStudent == student10 && advisoryStudentSp == student10F || advisoryStudent == student11 && advisoryStudentSp == student11F) {
        if (getvalue('i' + columnAmount) > 0) {
          amount = amount + getvalue('b' + columnAmount) + ' ' + getvalue('a' + columnAmount) + ': ' + '$' + amountowed + '<br>';
        }
      }
    }
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Status Calculator');
  var LastRow = ss.getLastRow();
  var columns = 3;
  var columnassignments = 3;
  var columnEnrichment = 3;
  for (columnEnrichment; columnEnrichment <= LastRow && columnEnrichment <= 160; columnEnrichment++) {
    var advisoryStudent = getvalue('a'+columnEnrichment);
    var advisoryStudentSp = getvalue('b' + columnEnrichment);
    if (advisoryStudentSp == student1F || advisoryStudent == student2 && advisoryStudentSp == student2F || advisoryStudentSp == student3F || advisoryStudentSp == student4F || advisoryStudentSp == student5F || advisoryStudentSp == student6F || advisoryStudentSp == student7F && advisoryStudent == student7 || advisoryStudentSp == student8F || advisoryStudent == student9 && advisoryStudentSp == student9F|| advisoryStudent == student10 && advisoryStudentSp == student10F || advisoryStudent == student11 && advisoryStudentSp == student11F) {
      if (Utilities.formatDate(getvalue('g' + columnEnrichment), 'EST', 'HH') > 0 || Utilities.formatDate(getvalue('g' + columnEnrichment), 'EST', 'mm') > 0){
        enrichment = enrichment + getvalue('b' + columnEnrichment) + ' ' + getvalue('a' + columnEnrichment) + ': ' + Utilities.formatDate(getvalue('g' + columnEnrichment), 'EST', 'HH') + ' hours ' + Utilities.formatDate(getvalue('g' + columnEnrichment), 'EST', 'mm') + ' minutes <br>'
      } 
    }
  }

}

编辑:

这部分只有一列的名称列表,在整个 200 行列中搜索一个单词并返回包含该单词的行,如果大于 5 则再次返回。

如果我只查找大于或等于 5 的数字并使用 getvalue 函数,那将是返回值为 5 或更大的名称的最有效方法吗?

function getValues(CellName) {
 return SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet2').getRange(CellName).getValues(); 
}

function setvalue(CellName, value) {
 return SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet2').getRange(CellName).setValue(value); 
}

function test(i) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sh2 = ss.getSheetByName('Sheet2');
  var data = sh2.getRange('A1:C200').getValues();
  var amount = sh2.getRange('c1:c200').getValues()
  var findthis = sh2.getRange('e1').getValues();

  var acol = sh2.getRange(1,sh2.getLastRow(),1,1).getValues();
  var bcol = sh2.getRange(1,sh2.getLastRow(), 2, 1).getValues();

  var test = acol.join().split(',');
  var test2 = bcol.join().split(',');

  for (i = 0; i<data.length; i++) { //search all rows
      if ('wet' == data[i][0]) { //finds wet in the data column and returns row
       Logger.log('testing' + ' row '  + (i+1)) 

       if (amount[i][0] >= 5) { //search if c >= 5
         Logger.log('Larger ' + ' row '  + (i+1)) 
       } 

      }

    }

}

【问题讨论】:

    标签: google-apps-script


    【解决方案1】:

    我建议您按自然网格范围将您的数据分组到arrays,然后按数组索引访问这些值。

    大致如下:

    function teacher1() {
      var ss = SpreadsheetApp.getActiveSpreadsheet();
      var sh_1 = ss.getSheetByName('sheet1');
      var sh_2 = ss.getSheetByName('sheet2');
      ...
       // Get all related values into array & retrieve each row record by index
       var student = sh_1.getRange("B3:C13").getValues(); // student[row][col] :ex: student11 => student[12][0]::student11F => student[12][1]
    
      ...
      // remove the for loop & get all values in a col with one call per col
      //(this could be optimized further)
      var a_col = sh_2.getRange(1, sh_2.getLastRow(), 1, 1).getValues(); // col a rows 1-lastrow()
      var b_col = sh_2.getRange(1, sh_2.getLastRow(), 2, 1).getValues(); // col b rows 1-lastrow()
    
      // Flatten the array to make searching that column easier
      var advisoryStudent = a_col.join().split(",")
      var advisoryStudentSp = b_col.join().split(",")
      // etc ...
    
    
      // To check if student11 is in advisoryStudentSp: (can loop through students here)
      // -1 means not found
      // any other number is the index position of `advisoryStudentSp[i]`
      // if 5 is returned then student11 matched the value in sheet2 colB row6
      Logger.log("student11 is in position: %s", advisoryStudentSp.indexOf(student[12][0]))
    
    }
    

    编辑:添加了一些重要的.getValues()

    【讨论】:

    • 感谢您的回复。上面我快速编辑了一些东西来测试一个示例代码。由于缺乏经验,我无法像您一样使用它,但它非常接近。请您看一下并告诉我这是否是一种有效的方法?
    • col A 中的值是否唯一?如果是这样,我会indexOfCode Review 可能是问这个问题的更好地方。有很多方法可以解决这个问题,你的方法可以同时减少配额命中 - 这是主要问题。对于您的getRange(),我会使用getLastRow()
    • 我以为我已经回复了。我很抱歉。有些是独一无二的,但并非全部都是,这就是我遇到的问题。我目前已根据我的需要编辑了上述脚本,它在没有计时器的情况下完美运行(快速,但仍然是科学怪人)。在计时器上,它可以工作,但有时它声称有太多的点击主要是因为试图通过所有 180 行。由于某种原因,我无法获得 a_col.join().split(","),您有我可以尝试的示例吗?
    • 所有a_col.join().split(",") 所做的都是将[[1],[2],[3]] 之类的数组展平为[1,2,3] ,这使得使用indexOf() 很有用。那是假设该列中的值是唯一的,因为它们不是 for 循环可能是最好的选择。会将数据范围更改为sh2.getRange(1, sh_2.getLastRow(), 1, 3).getValues() - 这样您就不会添加额外的空行来循环。它将获取数据的最后一行
    • 对于 ""A1:C" 的范围值应该是 sh2.getRange(1, 1, sh_2.getLastRow(), 3).getValues()
    【解决方案2】:

    您需要使用 Range.getValues() 一次性读取整个工作表或相关范围,而不是使用 getValue() / getAdvisee() 公式逐一检索单元格值,然后使用数组。

    这里的关键问题是每次调用 Range.getValues() 都会消耗大量时间,无论是一次读取 100 个单元格还是单个单元格值。因此,您当前一次读取一个单元格的方法非常缓慢(如您所见)。

    以这种方式重构太大,无法作为我的答案的一部分,但是一旦完成,这个脚本将在几秒钟内运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-01
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-19
      • 1970-01-01
      • 2011-01-03
      相关资源
      最近更新 更多