You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Sheets脚本首次循环正常执行,后续抛出“Exception: You can't hide all the sheets in a document”错误求助

Google Sheets脚本首次循环正常执行,后续抛出“Exception: You can't hide all the sheets in a document”错误求助

看起来你的问题出在重复多次打开同一个工作簿导致的对象状态不一致,加上变量重复声明带来的混淆。让我帮你梳理一下问题并给出修复方案:

问题根源分析

  1. 你在处理每个工作簿时,多次调用SpreadsheetApp.open(workBook),每次调用都会创建一个全新的电子表格对象实例。这可能导致不同实例之间的状态不同步——比如某个实例里的Current表状态和另一个实例里的不一致,触发隐藏所有表的错误。
  2. 你在同一个循环块里重复声明了var sheets变量,虽然JavaScript允许,但这会让代码逻辑变得混乱,增加调试难度。
  3. 没有提前检查Current表是否存在,万一某个工作簿里的Current表意外丢失(虽然你说之前正常,但脚本运行时的状态可能有变化),就会导致所有表被隐藏,触发错误。

修复后的完整代码

function saveInvoice() {
  //This script will process all the mentor invoices as follows:
  // 1. Get all the workbooks in the invoice folder
  // 2. For each workbook:
  //    a. Turn the "Current" tab into a PDF and save it in the designated folder with filename "[mentor name]-[date].pdf"
  //    b. Rename "Current" to today's date
  //    c. Make a new "Current" from the blank invoice template
  //    d. Move the new Current to be the leftmost tab in the workbook
  //    e. Lather, rinse, repeat.

  //get the spreadsheets in the current folder
  var invoiceFolder = DriveApp.getFoldersByName("Fake invoices for testing").next(); //THE FOLDER NAME NEEDS TO BE UPDATED EVERY YEAR! This is the folder with the spreadsheet invoices.
  var invoiceSheets = invoiceFolder.getFilesByType(MimeType.GOOGLE_SHEETS);
  var today = new Date();
  var date = Utilities.formatDate(today, "GMT+1", "yyyy-MM-dd"); //get today's date and format it once outside the loop
  var targetFolder = DriveApp.getFolderById("13KcgTUC3sw1aAa3xQWY6FkY6GwAH0cT7"); // Folder id to save in a folder **NEEDS TO BE UPDATED EVERY YEAR**

  while (invoiceSheets.hasNext()) { // Loops through all Workbooks inside the folder.
    var workBookFile = invoiceSheets.next(); //get the next workbook file
    Logger.log("Processing Workbook:" + workBookFile.getName());

    // 关键修改:只打开一次工作簿,复用这个对象
    var ss = SpreadsheetApp.open(workBookFile);
    var currentSheet = ss.getSheetByName("Current");

    // 提前检查Current表是否存在,避免后续错误
    if (!currentSheet) {
      Logger.log("Skipping workbook " + workBookFile.getName() + ": No 'Current' sheet found");
      continue;
    }

    // 获取所有工作表,复用变量
    var allSheets = ss.getSheets();

    // Cycle through sheets and hide all except "Current"
    for (var i = 0; i < allSheets.length; i++) {
      var sheet = allSheets[i];
      if (sheet.getName() !== "Current") {
        sheet.hideSheet();
      }
    }

    // Generate PDF
    var pdfBlob = workBookFile.getBlob().getAs('application/pdf')
      .setName(currentSheet.getRange("A1").getValue() + "-" + date + ".pdf");
    var newFile = targetFolder.createFile(pdfBlob);
    Logger.log("Created PDF: " + newFile.getName());

    // Unhide all other sheets
    for (var i = 0; i < allSheets.length; i++) {
      var sheet = allSheets[i];
      if (sheet.getName() !== "Current") {
        sheet.showSheet();
      }
    }

    // Rename "Current" to today's date
    currentSheet.setName(date);

    // Make a copy of the "Blank" sheet and rename it "Current"
    var blankSheet = ss.getSheetByName('Blank');
    if (blankSheet) {
      var newCurrentSheet = blankSheet.copyTo(ss).setName('Current');
      // Move new Current to leftmost tab
      ss.setActiveSheet(newCurrentSheet);
      ss.moveActiveSheet(0);
    } else {
      Logger.log("Warning: No 'Blank' sheet found in workbook " + workBookFile.getName());
    }
  }
}

主要修改点说明

  1. 复用工作簿对象:在循环内只调用一次SpreadsheetApp.open(workBookFile),将结果保存为ss变量,后续所有操作都基于这个对象,确保状态一致。
  2. 提前检查关键表存在性:在处理前检查Current和Blank表是否存在,避免因表缺失导致的错误。
  3. 变量优化:
    • 将日期格式化移到循环外,避免重复计算。
    • 提前获取目标文件夹,避免循环内重复调用DriveApp.getFolderById。
    • 避免重复声明变量(比如原来的sheets),改用更清晰的变量名(allSheets)。
  4. 增加日志信息:添加更多日志,方便调试时查看执行状态。

这样修改后,应该就能解决你遇到的“不能隐藏所有工作表”的错误了,同时代码的可读性和稳定性也会提升不少。

备注:内容来源于stack exchange,提问作者murph

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 13:27:59