Google Apps脚本查找行的最快方法?

时间:2015-03-30 11:43:17

标签: google-apps-script

我试图找出最快的方法是从值与我的查询匹配的行中获取一些数据,我目前正在使用此代码:

var spr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('CustomerList'); 
  var klantNummer = array1[0].toString();
  var emailgebruiker = Session.getActiveUser().getEmail();      
  var data = spr.getDataRange().getValues(); 
  for(n=0;n<data.length;++n){ 
    if(data[n][0].toString() == klantNummer){ //.match(klantNummer)
      data[n][21] = emailgebruiker

   var KlantNR = data[n][0];
   var Email = data[n][3];
   var Stad = data[n][12];          
   var Taalschool = firstToUpperCase( data[n][13].toString() );    
   var Cursus = firstToUpperCase( data[n][14].toString() );      
   var Weken = data[n][15];
   var Accommodatie1 = data[n][17];
   var TypeAccommodatie = data[n][18];
   var TypeKamer = data[n][19];
   var VertrekDatum1 = data[n][20];

    };
  }
  spr.getRange(1,1,data.length,data[0].length).setValues(data); 

当我在一张小纸张中使用它时效果很好但是当纸张变大时它开始变慢,有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

有一种快速解决方案可以解决某些情况。找到匹配后你可以打破循环。但是,如果您的数据位于列表底部,则无效。

if(data[n][0].toString() == klantNummer){ //.match(klantNummer)
   data[n][21] = emailgebruiker;
   var KlantNR = data[n][0];
   var Email = data[n][3];
   .
   . 
   .  
   var VertrekDatum1 = data[n][20];
   break;
 }

加速搜索的第二种方法是通过搜索键,klantNummer以及执行二进制搜索来订购数据。在不知道您的数据集的情况下,虽然这可能不会更快,因为您首先需要在搜索之前对集合进行排序。 您可以通过按客户编号预先排序的客户重复表来解决此问题。这将是您用来搜索的工作表。

这是javascript中的二进制搜索。这是https://github.com/Wolfy87/binary-search。我修改它以使用多维数组作为getValues()返回它们的方式。搜索索引中的最后一个参数,其中客户编号所在的列。下面的代码在2000个记录中的数据集中返回大约.139秒的行号。

  function myFunction() {
  var customerId = 11359;
  var ss = SpreadsheetApp.getActiveSheet();
  var range = ss.getDataRange();
  var customers = range.getValues();  
  var index = binarySearch(customers, customerId,0);

  Logger.log(index+1); // This is the Row in the spreadsheet.


}


/**
 * Performs a binary search on the provided sorted list and returns the index of the item if found. If it can't be found it'll return -1.
 *
 * @param {*[][]} list Items to search through.
 * @param {*} item The item to look for.
 * @return {Number} The index of the item if found, -1 if not.
 */
function binarySearch(list, item,column) {
    var min = 0;
    var max = list.length - 1;
    var guess;
    var column = column || 0

    while (min <= max) {
        guess = Math.floor((min + max) / 2);

        if (list[guess][column] === item) {
            return guess;
        }
        else {
            if (list[guess][column] < item) {
                min = guess + 1;
            }
            else {
                max = guess - 1;
            }
        }
    }

    return -1;
}

答案 1 :(得分:2)

我发现在Drive中保存为文本文件的JSON对象工作得非常快,读取6mb文本文件然后在200毫秒内解析。有了这个,您可以将klantNummer的所有行保存到对象并调用它,获取行并获得所有值,不到1秒,如下:

保存,更新并获取klantNummer示例:

function saveFile(){
  var klanNumbers = {'ben@gmail.com ': 3, 'dora@gmail.com' : 12, 'ksd@gmail.com' : 33};
  return DriveApp.createFile('klanNumbers', JSON.stringify(klanNumbers));
}

function updateFile( newKlanNumb, klanLine ){
  var klanNumbFile = DriveApp.getFilesByName('klanNumbers').next(),
      file = JSON.parse(file.getAs("application/none").getDataAsString());

  if( file[ newKlanNumb ] )
    file[ newKlanNumb ] = file[ newKlanNumb ] + ',' + klanLine;
  else
    file[ newKlanNumb ] = klanLine;

  klanNumbFile.setTrashed(true);

  return DriveApp.createFile('klanNumbers', JSON.stringify( newKlanNumb ));
}

function getKlanNumbers( klanNumb ){
  var file = DriveApp.getFilesByName('Transactions').next(),
      info = file.getAs("application/none").getDataAsString(),
      klanNumbers = JSON.parse(info);

  return klanNumbers[klanNumb];
}