【问题标题】:google script too slow, is there a way to speed it up?google script 太慢了,有没有办法加快速度?
【发布时间】:2021-02-17 08:59:54
【问题描述】:

我有一个脚本,它一直是爱的劳动,我花了一段时间才弄清楚,但现在我已经开始工作了,当在包含少量数据的测试表上使用它时,它可以完美运行而没有问题.

在包含超过 40,000 行数据的实时工作表上使用它时会出现问题,脚本根本无法在允许的 30 分钟内完成。

由于我对脚本很陌生,我想知道我是否以某种方式使我的脚本不必要地变长了。

我在下面粘贴了我的脚本,但让我解释一下我想要实现的目标。

每个客户都有自己的销售报告,并且由于隐私原因,他们需要分别放在不同的表格上。 所以我有我的 MasterData 表和另一个我命名为 URL 的表 在 URL 中,我有一个包含客户姓名和电子表格 ID 的表格。

我的脚本实现的是按客户名称过滤我的 MasterData,复制所有可见的数据,然后将其粘贴到客户的个人电子表格中,并从 URL 的工作表中获取 ID。

我花了很长时间才达到这一点,所以我希望有一种方法可以加快速度。

function get_data(){
  var s1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MasterSheet");
  var s3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("URL's")
    var range = s1.getRange(1, 1, s1.getLastRow(), s1.getLastColumn())
  var filter = range.getFilter() || range.createFilter();
  var foo_index = 2; // column A
  

  var data = []
  for (var j = 1;j<s3.getLastRow(); j++){
   var filterName = s3.getRange(j+1, 1).getValue()
   var criteria = SpreadsheetApp.newFilterCriteria().whenTextEqualTo(filterName).build();
  var values = s1.getFilter().setColumnFilterCriteria(1, criteria)
   var id = s3.getRange(j+1,2).getValue()
   var s2 = SpreadsheetApp.openById(id).getSheetByName("MasterSheet")
   var clear = s2.getRange(2,1,s2.getLastRow(),s2.getLastColumn()).clear({contentsOnly: true})
   var data = []
   for (var i = 1; i < s1.getLastRow(); i++){
    if(!s1.isRowHiddenByFilter(i+1)) {
      var row_data = s1.getRange(i+1, 1, 1, s1.getLastColumn()).getValues()
      data.push(row_data[0])
    }
   }
   var paste = s2.getRange(s2.getLastRow()+1,1,data.length,25).setValues(data)
  }
}

【问题讨论】:

  • 我认为对于你的情况Code Review 是一个更合适的地方,因为这甚至不是你的问题。我可以立即告诉您的唯一一件事是,当您已经拥有s1 的工作表时,使用s2 完全没用。
  • 我同意@Raserhin。如果您摆脱 for 循环中的 getRange.getValue 语句并在 for 循环之外使用 getValues 并使用数组来代替,您将获得主要的性能提升。我只是随机找到了一个示例来向您展示我的意思:example

标签: google-apps-script google-sheets


【解决方案1】:

我不得不对标头名称进行一些猜测,但如果你会仔细阅读这段代码,就像我尝试过你的代码一样,那么我认为你会想出一个更快的解决方案。

function get_data() {
  const ss = SpreadsheetApp.getActive();
  const s1 = ss.getSheetByName("MasterSheet");
  const s3 = ss.getSheetByName("URL's");
  const [mhA, ...mdata]=s1.getDataRange().getValues();
  const [chA, ...cdata]=s3.getDataRange().getValues();
  let midx = {};//index fo mastersheet by column name
  let cidx = {};//index to url's sheet by column name
  mhA.forEach((h, i) => { midx[h] == i });
  chA.forEach((h, i) => { cidx[h] == i });
  
  cdata.forEach((cr,i)=>{
    let data = [];
    let cname=cr[cidx['CustomerName']];//I dont really know what you have in s3 for headers so I guessed
    let cssid=cr[cidx['ID']];
    mdata.forEach((mr,j)=>{
      if(mr[midx['CustomerName']]=cname) {//if customer name from s3 matches customer from s1 the save that row in data
        data.push(mr);
      }
    });
    let css=SpreadsheetApp.openById(cssid);
    let csh=css.getSheetByName("MasterSheet");
    csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);// put all rows into customer mastersheet
  });
} 

【讨论】:

    猜你喜欢
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2022-01-28
    相关资源
    最近更新 更多