【问题标题】:Want to run same script on each active sheets of shared google spreadsheet想要在共享的谷歌电子表格的每个活动表上运行相同的脚本
【发布时间】:2021-05-24 05:54:24
【问题描述】:

我对编码很陌生,只是想从 Google 表格开始学习一些东西。我有一个仅在一张纸上运行的示例脚本,它将被共享电子表格。这是我的脚本

<!-- begin snippet: js hide: false console: true babel: false -->
var sheet =`enter code here` ["Main01"];
var optionList = ["Options"];
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet);
var wsOptions = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(optionList);
var options = wsOptions.getRange(2,1,wsOptions.getLastRow()-1,3).getValues();
var firstLevelColumn = 1;
var secondLevelColumn = 2;
var thirdLevelColumn = 3;


//Begins - main functions

function myFunction() {
} //End of myFunction


function onEdit(e) {
    var activeCell = e.range;
    var val = activeCell.getValue();
    var r = activeCell.getRow();
    var c = activeCell.getColumn();
    var wsName = activeCell.getSheet().getName();
    
    if(wsName == sheet && c == firstLevelColumn && r > 1 ){
        firstLevelList(val,r);
    } else if (wsName == sheet && c == secondLevelColumn && r > 1 ) {
        secondLevelList (val,r);
      }
} //End of function - onEdit


function firstLevelList(val,r) {
    if(val == ""){
        ws.getRange(r,secondLevelColumn).clearContent();
        ws.getRange(r,secondLevelColumn).clearDataValidations();
        ws.getRange(r,thirdLevelColumn).clearContent();
        ws.getRange(r,thirdLevelColumn).clearDataValidations();
    } //End of inner if statement 
      else { 
        ws.getRange(r,secondLevelColumn).clearContent();
        ws.getRange(r,thirdLevelColumn).clearContent();
        ws.getRange(r,thirdLevelColumn).clearDataValidations();
        
        var filteredOptions = options.filter(function(op) { return op[0] == val });
        var applyList = filteredOptions.map(function(op) { return op[1] });
        var cell = ws.getRange(r,secondLevelColumn);
        
        applyCellValidation(applyList,cell);
      } //End of else statement
} //End of function - firstLevelList


function secondLevelList(val,r) {
    //similar to firstLevelList with next level validation
} //End of function - secondLevelList


function applyCellValidation(list,cell) {
      var rule = SpreadsheetApp.newDataValidation().requireValueInList(list).setAllowInvalid(false).build();

      cell.setDataValidation(rule);
} //End of function - CellValidation

我想从代码中实现的一些任务-

  1. 打开电子表格时自动运行脚本 - 可能使用 onOpen() 触发器。怎么不知道
  2. 由于它将是共享电子表格,因此我希望在任何用户访问时为每个活动工作表运行脚本。

【问题讨论】:

  • 当您打开电子表格时 - 活动工作表将始终是第一个工作表(Sheet1 - 如果未重命名)。这意味着检测活动工作表onOpen 的脚本将始终检测电子表格的第一张工作表。是你想要的吗?如果您希望脚本在用户手动更改活动工作表后再次运行 - 这不会发生 onOpen。此外,目前您的脚本已设置为onEdit - 您想保持此功能(脚本应同时运行onOpenonEdit)还是只运行onOpen
  • @ziganotschka 我想让它工作,只要用户打开和编辑任何工作表选项卡。脚本以类似方式适用于电子表格的所有工作表选项卡。谢谢
  • 在这种情况下,您需要(除了您的 onEdit 触发器之外)一个 onSelectionChange 而不是 onOpen 触发器 - 请参阅我的答案。

标签: javascript google-apps-script google-sheets


【解决方案1】:

要检测活动工作表的变化,您需要使用onSelectionChange 触发器

onSelectionChange 触发器允许您估计新选择与旧选择一样属于同一工作表 - 还是属于不同工作表。

有一个优雅的implementation@Diego开发。

将它应用到您的案例中,您应该在现有脚本中添加以下功能:

function onSelectionChange(e) {
  var activeCell = e.range;
  if (activeSheetChanged(activeCell.getSheet().getSheetId())) {
    var val = activeCell.getValue();
    var r = activeCell.getRow();
    var c = activeCell.getColumn();
    var wsName = activeCell.getSheet().getName();
    if(wsName == sheet && c == firstLevelColumn && r > 1 ){ 
        firstLevelList(val,r);
    } else if (wsName == sheet && c == secondLevelColumn && r > 1 ) {
        secondLevelList (val,r);
      }
   }
} //End of function 

function activeSheetChanged(newSheetId) {
  const key = 'activeSheetId';
  const cache = CacheService.getUserCache();
  let properties;
  const savedSheetId = getSavedSheetId();
  if (savedSheetId != newSheetId) {
    saveSheetId(newSheetId);
    return true;
  }
  return false;
  
  /**
   * Get the saved sheet ID from the Cache/Properties.
   * @returns {Number}
   */
  function getSavedSheetId() {
  console.log("called")
    let savedSheetId = cache.get(key);
    if (savedSheetId == null) {
      properties = getProperties();
      savedSheetId = properties.getProperty(key);
      cache.put(key, savedSheetId);
    }
    return cache.get(key);
  }
  
  /**
   * Save the sheet ID to the Cache & Properties
   */
  function saveSheetId(sheetId) {
    properties = properties ? properties : getProperties();
    properties.setProperty(key, sheetId);
    cache.put(key, sheetId);
  }
  
  /**
   * @returns {PropertiesService.Properties}
   */
  function getProperties() {
    return PropertiesService.getUserProperties();
  }
}

还有:

如果要将工作表名称与“Main01”进行比较,则需要将第 1 行从 var sheet = ["Main01"]; 更改为 var sheet = "Main01"; 以使脚本正常工作。

【讨论】:

    猜你喜欢
    • 2019-11-29
    • 2013-12-27
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    相关资源
    最近更新 更多