簡體   English   中英

Google Apps 腳本迭代電子表格非常慢

[英]Google Apps Script Iterating over Spreadsheets very slow

第一次發帖,看了好久:)

我剛剛編寫了我的第一個 google 應用程序腳本來整理來自 14 個電子表格的信息,每個工作表有 2-30 個工作表到一個報告電子表格中。

該腳本運行良好,它檢查單個列的數據,如果找到,則獲取電子表格名稱、工作表名稱、該行的第一列數據和檢查列中的數據,並將其作為數據子數組添加到數組中。

然后計算子數組數組的面積並將數據寫入報告文件(腳本運行的地方)。

我唯一的問題是運行腳本大約需要 2 分鍾。

我想知道我的方法是否效率低下,並希望有人可以查看腳本並讓我知道我是否犯了一些錯誤?

開始:

/**
* Retrieves all the rows in the active spreadsheet that contain data and logs the
* values for each row.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/

function getFaults() {
/** opens each spreadsheet for Liddon and examines the "Report/Replace" column "F"
if there is data there then  get the 
[Sheetname], [fault area (column "A" row relative to the "F" field found)] and the ["F" field  data]
 **/
var reportsheet = SpreadsheetApp.getActiveSheet();
var reportdata = []
var reportrow = 0

var liddonblocks = [ 
"1APshQevK7iZxhP7--zmtuM3K6dPTgTZjmNarQ6CEsV4", "1riCQMOa38jo4nCD4qjW1BFZKk5xpXFZiCXHzXpiYKIU",   "1NTKXmted1-U12MiqvCGRuYBdhPy1_eLiPn7v8_oVKFE", "1RKOJUNNi5TAg5dETZDtLjZOkUSheuguzmtdPelMclMI",
"1b5-fzCp0wzW8llpUc_6xi1iTFzsapZh9ASSFgDYt4WU", "1qJtY37K0zwoJcz7LdyHhWgkypRMP9LabBchNLM4Fgow",   "1yvf4W8-SkfTH-n-PdDNQeyEDEz-shzTe-Id57S_YB2M", "1ETZc1xeNGXU6ipb1XQiD8SiIyRXzZtiJfS4AClKroJk",
"1tJ5u3Hv0uz-n2cdw-QYixKnuMG9skvrUbz1UROhIm34", "1DjhmIdD0GrPxR-fv7pCPkIwIyfai5BHsK9GhT-Hcs3k", "15w39NZZIacD1OfiTWG1E3HmOhV0B_e2Jsuan_ySwf2Q" , "1cK2HBLEftYOZEkCcxs1TX1PxcJRiKTZpQrcsOfE4B1s",
"16W_bfMKk98wkLpEmm2Q68Ta_SrCA8EBarQyGF2yfm18","1_Z_tgF5UAfq3fxPsDEe40z2GZSehhL-u4hEuVszrbn8" ]

// loop through the spreadsheets
for (block = 0; block < liddonblocks.length; block++) { 
  //open the spreadsheet using the index from the liddonblocks list
  var ss = SpreadsheetApp.openById(liddonblocks[block]);
  //get all of the sheets within the spreadsheet
  var sheets = ss.getSheets();

//loop through each sheet in each spreadsheet using the length of the number of sheets in the     spreadsheet as the index
for (var sheetnum = 0; sheetnum < sheets.length; sheetnum++) {
  //get an array of all data in the sheet
  //assigns array in the form of: [[area, fault], [Bedroom, Broken Bed], [Bathroom, ]] 
  //where each sub-array is a row of data starting at row 1 eg: [[row1-col1, row1-col2...],[row2-col1, row2-col2...]...]
  data = sheets[sheetnum].getDataRange().getValues();
  //get the text name of the sheet
  name = sheets[sheetnum].getSheetName();

  // iterate over the data set and look for values in the  5th column, starting at row 7 to exclude the headers.
  // this is the column named "Report / Replace "
  for (var count = 7; count < data.length; count++) {
    if (data[count][5] != "" && data[count][5] != 0) {
      //if there is data in the 5th column of the row then append the following data to the reportdata array and a sub-array
      // [ sheetname, columnA, columnF ]
      reportdata[reportrow] = [ ss.getName(), name, data[count][0], data[count][5]]
      //increment the reportcount variable so any further hits on data in column 5 are created as sequentail sub-arrays in the reportdata array.
      reportrow++
    }
  }
}
}
//write the contents of reportdata to the console
var range = reportsheet.getRange(2,1,reportrow,reportdata[0].length);
range.setValues(reportdata);
}

/**
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the readRows() function specified above.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function onOpen() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
  name : "Update Report",
  functionName : "getFaults"
 }];
 spreadsheet.addMenu("Keble Scripts", entries);
};

首先,查看此頁面上的信息。

我經歷過的三件事會讓你慢下來:

  1. 多次調用外部服務
  2. 在循環中調用SpreadsheetApp.flush()以強制更新工作表。
  3. 經常調用Range.getValue()

對於第一部分,嘗試批量調用。 例如,如果您請求本地貨幣和外國貨幣的匯率,請嘗試在一個請求中發送一堆查詢。

對於第二部分,除非真的有必要,否則不要調用此方法。

對於第三部分,嘗試修改您的代碼,以便您可以調用此方法一次並隨其結果移動,而不是在多個方法中調用它以獲得相同的結果。

提示:為了避免修改許多方法參數,只需在方法樹調用的開頭傳遞一個對象並用參數填充它。 這樣你就不必修改你傳遞的每個方法來添加\\刪除參數。 這是一個適用於所有具有函數的編程語言的概念。

我同意 Serge 的評論,即這段代碼已經得到了很好的優化,打開許多電子表格需要一些時間。

我看到了一個改進的機會,但它對速度的影響可能很小(如果有的話)。 您可以將 ss.getName() 調用移出內部循環,而是在打開電子表格后立即將其分配給一個變量,然后在最內部的循環中引用該變量。

請注意,根據我的經驗,Google 服務調用的速度往往差異很大,因此有時可能會運行得更快或更慢。 您可以通過查看腳本編輯器的 Execution Transcript 中的 View 菜單來查看每次調用所花費的時間。

暫無
暫無

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

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