"The JavaScript runtime exited unexpectedly" 解析 Google 工作表时出错

"The JavaScript runtime exited unexpectedly" error when parsing through Google Sheets

我有一个函数 getFnF(),它遍历 Google Drive 文件夹及其所有子文件夹。当 getFnF() 遇到 Google Sheets 文件时,我让脚本解析 Google Sheets 文件并使用我的函数 getLinksFromSheet() 提取它找到的任何 URL 链接.这两个函数都有效,但在遍历 Drive 文件夹并在遇到的 Google 表格文件上调用 getLinksFromSheet() 大约 10 分钟后,我收到 The JavaScript runtime exited unexpectedly. 错误。有人知道会导致此错误的原因吗? Google Drive 文件夹非常大(子文件夹中共有约 500 个文件,其中约 75 个是 Google 表格)。代码如下:

function getFnF(folder) {
  var folder= folder || DriveApp.getFolderById("0AFZNRhJpE8LKUk9PVA"); //hard goded DEP-Gotham folder
  
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('Sheet1');
  var files=folder.getFiles();
  
  while(files.hasNext()) {
    var file=files.next();
    var firg=sh.getRange(sh.getLastRow() + 1,level + 1);
    firg.setValue(Utilities.formatString('File: %s', file.getName()));
    Logger.log(file.getName())
    //if (file.getMimeType() == 'application/vnd.google-apps.document') {getAllLinks(file.getId(), false);};
    //if (file.getMimeType() == 'application/vnd.google-apps.presentation') {getLinksFromSlides(file.getId());};
    if (file.getMimeType() == 'application/vnd.google-apps.spreadsheet') {getLinksFromSheet(file.getId());};
  }

  var subfolders=folder.getFolders() 
  while(subfolders.hasNext()) {
    var subfolder=subfolders.next();
    var forg=sh.getRange(sh.getLastRow() + 1,level + 1);
    forg.setValue(Utilities.formatString('Fldr: %s', subfolder.getName()));
    level++;
    getFnF(subfolder);
  }

  level--;
}

function getLinksFromSheet(sheetId){
 var ss = SpreadsheetApp.openById(sheetId); 
 var sheets = ss.getSheets();
 var parentDocName = ss.getName();

 var destSs=SpreadsheetApp.getActive();
 var destSh=destSs.getSheetByName('Extracted Links');
 
 sheets.forEach(sheet => {
  var rangeData = sheet.getDataRange();
  var lastColumn = rangeData.getLastColumn();
  var lastRow = rangeData.getLastRow();
  var searchRange = sheet.getRange(1,1, lastRow, lastColumn);
  //var rangeValues = searchRange.getValues();
  var rangeValues = searchRange.getRichTextValues();


    for (var i = 0; i < lastRow; i++){
      for (var j = 0; j < lastColumn; j++){
       
        const runs = rangeValues[i][j].getRuns();

        for (const v of runs) {
           var nextLink = v.getLinkUrl();
           if (nextLink != null) {
           var row = destSh.getLastRow() + 1;
           var r1=destSh.getRange(row, 1);
           r1.setValue(parentDocName);
           var r2=destSh.getRange(row, 2);
           r2.setValue(nextLink);
           };
      }
    }
  }
});

为了解决您遇到的时间问题,我建议使用一个脚本来编写所有电子表格 ID,然后使用另一个脚本来处理它们 (运行 getLinksFromSheet())一次,然后将每一行标记为已完成,这样您就可以重新运行它直到完成。

Getrichtextvalue > getlinkURL 很慢wwwwwwwww,你无法绕过它。

问题很可能源于超出运行时执行的限制。

您可以使用 getFilesByType 进一步缩减列表并节省时间。也确实在您的代码中做了一些修改,但应该能够做同样的事情。他们上面应该有评论。请检查。

用法:

function getFnF(folder) {
  var folder = folder || DriveApp.getFolderById("0AFZNRhJpE8LKUk9PVA"); //hard goded DEP-Gotham folder

  var ss = SpreadsheetApp.getActive();
  var sh = ss.getSheetByName('Sheet1');
  // limit files to only google sheets
  var files = folder.getFilesByType(MimeType.GOOGLE_SHEETS);
  
  // assign getLastRow to lessen method calls
  var lastRow = sh.getLastRow();
  // initialize level value
  var level = 1;

  while (files.hasNext()) {
    var file = files.next();
    // I can use appendRow here, but I did't since column has a variable
    // and you might change it. Feel free to update if necessary
    var firg = sh.getRange(lastRow + 1, level + 1);
    firg.setValue(Utilities.formatString('File: %s', file.getName()));
    getLinksFromSheet(file.getId()); 
    // iterate lastRow
    lastRow++;
  }

  var subfolders = folder.getFolders()
  while (subfolders.hasNext()) {
    var subfolder = subfolders.next();
    // I can use appendRow here, but I did't since column has a variable
    // and you might change it. Feel free to update if necessary
    var forg = sh.getRange(lastRow + 1, level + 1);
    forg.setValue(Utilities.formatString('Fldr: %s', subfolder.getName()));
    level++;
    getFnF(subfolder);
    // iterate lastRow
    lastRow++;
  }
  // not sure what this does but you can freely remove this if not being used
  level--;
}

function getLinksFromSheet(sheetId) {
  var ss = SpreadsheetApp.openById(sheetId);
  var sheets = ss.getSheets();
  var parentDocName = ss.getName();

  var destSs = SpreadsheetApp.getActive();
  var destSh = destSs.getSheetByName('Extracted Links');

  sheets.forEach(sheet => {
    // getDataRange already gets all the data
    var rangeData = sheet.getDataRange();
    // Flatten 2d array
    var rangeValues = rangeData.getRichTextValues().flat();
    
    rangeValues.forEach(v => {
      var link = v.getLinkUrl();
      if(link)
        // Use appendRow instead. Adjust array if needed to be in a different column.
        destSh.appendRow([parentDocName, link]);
    });
  });
}

运行时差:

6 秒运行是上面的优化代码,而 7 秒运行是您的代码。

测试条件:

  • 父文件夹中有两个 sheet 个文件,1 个子文件夹中有一个 sheet 文件:
  • 每个传播sheet有2个sheet,每个sheet有1个link.
  • 父文件夹有一个非sheet文件。

注:

  • 考虑到少量文件的显着运行时间差异,当然这将对大量文件产生更大的影响。
  • 如果你想包含其他类型的文件,如果你对每个文件类型有不同类型的处理,那么你需要创建一个单独的循环来处理每个文件类型。
  • 您也可以将 2 个 getFilesByType 输出加入 1 个数组,但是从不同的文件类型获取 link 可能会有所不同,因此单独的循环会更安全。