簡體   English   中英

復雜的轉置超過了 Google Apps 腳本中的運行時間

[英]Complex transpose exceeding run time in Google Apps Script

我在單列中接收數據,必須將其轉換為單獨的記錄。 一些記錄的長度為 12 個字符,其他的為 10 個,其余為 9 個。此外,10 個和 9 個字符長的記錄中的后 2 個值必須分別向右移動 1 個和 2 個字段。 給定記錄中的第一個值始終是日期。 我創建了以下代碼運行良好,除了它在大約 6 分鍾和 77 條記錄后超時。 我需要能夠處理 15 倍甚至更多。

我在每個 if 語句的 else 部分嵌入了日期對象的計算,並嵌套了后續的 if 語句,以減少不必要的計算。 這讓我從大約 48 條記錄增加到 77 條。

非常感謝任何聰明的見解🙂


function transposeNew(){
  let ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  let lr = ss.getRange("A13").getDataRegion().getLastRow();
  let sr = 13

  // get the data column
  let data = ss.getRange(sr,1,lr-sr,1).getValues();

  // set up the rows loop
  let pasteRow = 2;
  let arrayField = 0;
  while (arrayField < data.length){
    //use the new Date() constructor to create a date object with the date value passed
    let isDate12 = new Date(data[arrayField+12]).getFullYear(); //processed; size input;record should include 12 rows & 13th should be a date to begin the next row
    if (isDate12 === 2020) {
      let record = data.slice(arrayField, arrayField+12);
      let recordTr = transposeSub(record);
      ss.getRange(pasteRow, 5, 1, 12).setValues(recordTr);
      arrayField = arrayField + 12;
    }
    else {
      let isDate10 = new Date(data[arrayField+10]).getFullYear(); //unprocessed;size input
      if (isDate10 === 2020) {
        let record = data.slice(arrayField, arrayField+10);
        let record1 = record.slice(0,8);
        let record1Tr = transposeSub(record1);
        let record2 = record.slice(8,10);
        let record2Tr = transposeSub(record2);
        ss.getRange(pasteRow, 5, 1, 8).setValues(record1Tr);
        ss.getRange(pasteRow, 14, 1, 2).setValues(record2Tr);
        arrayField = arrayField + 10;
      }
      else {
        let isDate9 = new Date(data[arrayField+9]).getFullYear(); //unprocessed;no size 
          input
        if (isDate9 === 2020) {
          let record = data.slice(arrayField, arrayField+10);
          let record1 = record.slice(0,7);
          let record1Tr = transposeSub(record1);
          let record2 = record.slice(7,9);
          let record2Tr = transposeSub(record2);
          ss.getRange(pasteRow, 5, 1, 7).setValues(record1Tr);
          ss.getRange(pasteRow, 14, 1, 2).setValues(record2Tr);
          arrayField = arrayField + 9;
        }
      }
    }
    pasteRow ++;
  }
}

function transposeSub(a)
{
  return Object.keys(a[0]).map(function (c) { return a.map(function (r) { return r[c]; }); });
}

我看到您創建了一個循環,並在此while語句中多次調用 SpreadsheetApp 函數。 這會創建與電子表格的連接,讀取/更改其數據並多次關閉連接,這就是您的代碼運行時間過長的原因。 請查看GAS 最佳實踐批處理操作部分

你應該考慮放逐任何get/setValue()while相反,調用getValues()之前保持在JavaScript數組的所有值while再使用setValues()while在一次寫入所有輸出。 答案探討了所描述的概念。

所以事實證明問題是循環標准中的一個缺陷; 菜鳥錯誤。 存在數據異常,以至於一條記錄不符合任何 if 語句中的標准,因此循環一直在繼續。 我通過在工作表上的每條記錄旁邊插入 pasteRow 和 arrayField 的值來發現這一點,以便我可以看到它在哪里中斷。 有趣的是,記錄停止了,但 pasteRow 和 arrayField 值在應用程序退出之前持續到了 20,000 秒。

我確實注意到@Bruno Polo 和@Cooper 提供的反饋是正確的。 發布后不久,我對其進行了修改,將記錄推送到一個新數組中,並在完成后粘貼該數組。 由於上述相同的原因,這失敗了。 我想現在我明白了這個問題,我會回到那個版本。

謝謝你和我一起看這個。 這是一個非凡的專家社區,我從中學到了很多! 😁

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM