0

我在电子表格中使用自定义函数进行各种操作。我使用了缓存值的属性服务。此外,我已经将值范围发送到函数而不是调用该函数数百次。

我正在为一列使用100 行且不断增长的函数。我试图取两列,但它超过了30 秒的自定义功能限制。

不过,我收到了一些错误消息:

“错误:执行自定义功能的内部错误。”

因为同一个自定义函数同时50 次计算这100 行的答案。

我收到这条消息大约是 50 的 9 次。这并不奇怪,因为该功能正在计算很多东西。

如果可以在不同时间启动相同的自定义函数,或者如果自定义函数在出现错误消息后再次运行,则问题将得到解决。也许还有另一种方式。

我曾尝试应用指数退避,但我想用自定义函数不可能做到这一点。

我是 JavaScript 新手,我试图找到解决方法,但没有成功。

这是调用此自定义函数的电子表格的图像:

电子表格

这是我的自定义函数的代码:

// Names - range of names e.g. A4:A100
// function is returning number if it meets conditions 
function VSApmokyti(Names, date, place ) {

// if date and place is not arrays
if ( !Array.isArray(date) ) {
  return Names.map (function (d) { 
  return process (d[0], date, place)   
})

}
// if date and place is arrays
else {
return Names.map (function (d) { 
 return date[0].map (function (k, h) {
       return process (d[0], k, place[0][h])   
       })
       })
}
// this function can calculate no matter if date or place is arrays or values
function process(teacher, Vdate, school) {

  if (Vdate=="") {
    return null;
  }
  if (teacher=="") {
    return null;
  }



      // Taking from CACHE
  var cache = CacheService.getScriptCache();

  var teachersL = cache.get("TeachersL");
  teachersL = JSON.parse(teachersL);

  var teachers1 = cache.get("Teachers1");
  teachers1 = JSON.parse(teachers1);  

  var teachers2 = cache.get("Teachers2");
  teachers2 = JSON.parse(teachers2);

  var teachers3 = cache.get("Teachers3");
  teachers3 = JSON.parse(teachers3);  

  var teachers4 = cache.get("Teachers4");
  teachers4 = JSON.parse(teachers4);

  var dates = cache.get("Dates");
  dates = JSON.parse(dates);  

  var Schools = cache.get("Schools");
  Schools = JSON.parse(Schools);

  var number = cache.get("NumberScholars");
  number = JSON.parse(number);   



    if (!number) {

        // WRITING to CACHE
      var TeachersL = PropertiesService.getScriptProperties().getProperty('TeachersL');
      cache.put('TeachersL', TeachersL);
      teachersL = JSON.parse(TeachersL);


      var Teachers1 = PropertiesService.getScriptProperties().getProperty('Teachers1');
      cache.put('Teachers1', Teachers1);
      teachers1 = JSON.parse(Teachers1);


      var Teachers2 = PropertiesService.getScriptProperties().getProperty('Teachers2');
      cache.put('Teachers2', Teachers2); 
      teachers2 = JSON.parse(Teachers2);


      var Teachers3 = PropertiesService.getScriptProperties().getProperty('Teachers3');
      cache.put('Teachers3', Teachers3); 
      teachers3 = JSON.parse(Teachers3);


      var Teachers4 = PropertiesService.getScriptProperties().getProperty('Teachers4');
      cache.put('Teachers4', Teachers4); 
      teachers4 = JSON.parse(Teachers4);


      var Dates = PropertiesService.getScriptProperties().getProperty('Dates');
      cache.put('Dates', Dates); 
      dates = JSON.parse(Dates);


      var Schools = PropertiesService.getScriptProperties().getProperty('Schools');
      cache.put('Schools', Schools); 
      Schools = JSON.parse(Schools);


      var NumberScholars = PropertiesService.getScriptProperties().getProperty('NumberScholars');
      cache.put('NumberScholars', NumberScholars); 
      number = JSON.parse(NumberScholars);

    }


  // converting date from spreadsheet cell to be able check if condition
  Vdate = Vdate.toJSON();

        for(var y = 0; y < Schools.length; y++) { 
       if(Vdate==dates[y] && school==Schools[y]) { 
        if ((teacher==teachersL[y]) || (teacher==teachers1[y]) || (teacher==teachers2[y]) || (teacher==teachers3[y]) || (teacher==teachers4[y]))  {

          return number[y];

        }
      }
    }

}
}
4

2 回答 2

1

简短的回答

与其返回单个值的自定义函数,不如让它返回一个值数组。

解释

自定义函数可以返回单个值或值数组。如果您将自定义函数应用于连续的单元格,而不是将一个返回值的公式应用到每个单元格导致多次计算,您可以使用一个返回值数组的公式,但请记住自定义函数有 30 秒执行时间限制。见优化

如果您的函数超过 30 秒的限制,请使用将由自定义菜单、对话框、侧边栏、触发器或从 Google Apps 脚本编辑器调用的“常规”函数。此类功能对普通账户有 6 分钟的执行时间限制,对于注册了Early Access Program的 G Suite 账户有 30 分钟的执行时间限制。

于 2018-01-01T17:07:18.030 回答
0

有几种方法可以处理 Apps-script 中的错误。一种不太难的方法是使用 try and catch。例如,下面的代码会将函数运行时发生的任何错误的日志写入工作表。try and catch 也不会阻塞,所以即使有错误,函数也不会停止。这是一个将错误记录到 Google 工作表中的示例。

function somefunction(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var logSheet = ss.getSheetByName('Sheet1');

  try {
    myFunctionThatMightHaveErrors()
  } 

  catch(e){
    var now = new Data();
    var error = JSON.stringify(e);
    logSheet.appendRow([now, error]);
  }

}

仅供参考:除非您的域具有 Gsuite 商业帐户和应用程序制造商,否则应用程序脚本将运行任何功能长达 6 分钟。但如果需要,有一些方法可以绕过时间限制。

于 2018-01-01T08:11:34.847 回答