【问题标题】:Reordering Google Sheet worksheets by date按日期重新排序 Google Sheet 工作表
【发布时间】:2019-12-11 17:54:21
【问题描述】:

我有一个 Google 表格工作簿,其中有多个按日期命名的工作表。我正在尝试使用 Google Apps 脚本来 1)按时间倒序重新排列这些工作表,以及 2)然后将任何未来日期工作表移动到工作簿的末尾,因此第一张工作表始终是最新的工作表过去的日期。

第 1 步适用于以下代码:

function sortGoogleSheets() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  // Store all the worksheets in this array
  var sheetNameArray = [];
  var sheets = ss.getSheets();
  for (var i = 0; i < sheets.length; i++) {
    sheetNameArray.push(sheets[i].getName());
  }

  sheetNameArray.sort().reverse();

  // Reorder the sheets.
  for( var j = 0; j < sheets.length; j++ ) {
    ss.setActiveSheet(ss.getSheetByName(sheetNameArray[j]));
    ss.moveActiveSheet(j + 1);
  }
}

但第 2 步无法将未来日期的工作表移到末尾。没有产生错误,但工作表顺序没有改变。 'FutureSheetIDs' 是一个单列命名范围,其中包含日期 > 今天的工作表的工作表 ID(例如 938739529、532578283 等),即将移动到工作簿的末尾。

function resortFutureSheets() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var pos = ss.getNumSheets();
  var FutureSheets = ss.getRangeByName("FutureSheetIDs");
  for(var s=0 ; s < FutureSheets.length ; s++){
    var sh = ss.setActiveSheet(ss.getSheetByID(FutureSheets[s]));
    SpreadsheetApp.flush();
    Utilities.sleep(200);
    ss.moveActiveSheet(pos);
    SpreadsheetApp.flush();
    Utilities.sleep(200);
  }
}

任何关于为什么第 2 步不能按预期工作的指导将不胜感激。谢谢!

【问题讨论】:

  • 究竟什么“不起作用”?脚本失败并出现错误,如屏幕顶部的红色条所示?脚本运行良好,一些工作表移动,但并非所有工作表都按预期移动?
  • 抱歉,不,没有生成错误并且脚本完成,但它对工作表的顺序没有影响 - 没有按预期移动

标签: google-apps-script google-sheets


【解决方案1】:

尝试使用Sheets API,作为Advanced Sheets Service合并到Apps脚本中。

您可以检索和修改 工作表 ID工作表索引,如 documentation 中指定的那样:

电子表格中工作表的索引。添加或更新时 工作表属性,如果排除此字段,则添加工作表或 移动到工作表列表的末尾。更新工作表索引或 插入工作表,在“移动前”索引中考虑移动。 例如,如果有 3 张纸(S1、S2、S3)为了移动 S1 在 S2 之前,索引必须设置为 2。工作表索引更新 如果请求的索引与工作表相同,则忽略请求 当前索引,或者如果请求的新索引等于当前索引 工作表索引 + 1。

因此,根据您的要求,修改工作表的索引会很有用,您可以使用

enabling Advanced Sheets Service 之后,您可以更改工作表的索引(=位置),如下所示:

function myFunction() { 
 var ss=SpreadsheetApp.getActiveSpreadsheet(); 
 var FutureSheets=ss.getRangeByName("FutureSheets"); 
 var FutureIds=FutureSheets.getValues();
 var spreadsheetId=ss.getId();
 var sheets=ss.getSheets();
 for(s=0;s<FutureIds.length;s++)  { 
    if(FutureIds[s][0]==0){
      break;
    }else{
      var resource = {
        "requests": [
          {
            "updateSheetProperties": {
              "fields": "index",
              "properties": {
              "sheetId": FutureIds[s][0],
              "index": sheets.length
              }
            }
          }
        ]
      }
    Sheets.Spreadsheets.batchUpdate(resource, spreadsheetId)
    }
  }
}

【讨论】:

  • 谢谢你,这很好用。除了...因为命名范围 (FutureSheets) 在被过滤的单元格下方包含许多空白单元格(以应对被过滤的工作表 ID 的数量动态变化),当它达到数组中的第一个空白值时,脚本在技术上会失败,即使到那时,一切都已重新排序。有什么办法可以阻止它抛出这个错误? API call to sheets.spreadsheets.batchUpdate failed with error: Invalid value at 'requests[0].update_sheet_properties.properties.sheet_id.value' (TYPE_INT32), ""
  • 是的,有几种实现方式。例如,您可以在 for 循环中合并一个 if 语句来检查该行是否为空,请参阅我更新的答案。
【解决方案2】:

您需要获取工作表 ID 的值。

  var FutureSheets = ss.getRangeByName("FutureSheetIDs").getValues();

另外,请注意.getSheetByID('') 不存在。您必须进行第二次循环并根据其 ID 按名称选择工作表。

另外,我之前做过类似的事情,如果有大量工作表,工作表实际上不会更新它们的位置。这似乎是由于追逐问题,.flush() 没有影响。必须使用 F5 刷新工作表

Script to rename & reorder sheets based on table

【讨论】:

  • 谢谢,我已经使用 .getSheetByName() 并添加了一个额外的 var 来应用 .getValues,但它看起来确实很喜怒无常,只是有时会对工作表顺序产生影响。
  • 当它不起作用时,尝试使用F5刷新一次或两次。如果刷新后单张订单按照您的预期发生变化,那么您遇到了我提到的兑现问题。
【解决方案3】:

这似乎是最好的工作解决方案,虽然它很喜怒无常:

  function resortFutureSheets(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var pos = ss.getNumSheets();
  var FutureSheets = ss.getRangeByName("FutureSheetNames");
  var FutureSheetsArray = FutureSheets.getValues();
  for(var s = 0 ; s < FutureSheets.length; s++) {
    ss.setActiveSheet(ss.getSheetByName(FutureSheetsArray[s]));
    SpreadsheetApp.flush();
    Utilities.sleep(200);
    ss.moveActiveSheet(pos);
    SpreadsheetApp.flush();
    Utilities.sleep(200);
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多