有没有办法通过 Google sheet 上的复选框值来 add/delete 编辑者动态访问受保护的单元格?

Is there a way to add/delete editors' access to protected cells dynamically by checkbox values on a Google sheet?

我是 Google Apps 脚本的新手,对操纵不同编辑器的访问权限的问题感到困惑。我有10多个工作表和20个编辑,我需要根据他们的角色分配他们的访问权限。我正在考虑使用复选框来添加和删除他们的访问权限。到目前为止,这两个是我从其他人那里得到的代码。一个用于通过 checking/unchecking 框显示和隐藏时间戳,而另一个用于添加和删除编辑器。

对于时间戳

function runEmailAccess(){

var ss = SpreadsheetApp.getActiveSpreadsheet();
var sEditors = ss.getSheetByName('Sheet Name');
var sheet = SpreadsheetApp.openById("Sheet ID");

var nAddEditor = sEditors.getRange('A2').getValue();
if (nAddEditor != 0){
var vAddEditor = sEditors.getRange('A3:A'+nAddEditor).getValues();
sheet.addEditors(vAddEditor);
 }

var nRemoveEditor = sEditors.getRange('B2').getValue();
if (nRemoveEditor != 0){
var vRemoveEditor = sEditors.getRange('B3:B'+nRemoveEditor).getValues();

for (j=0;j<vRemoveEditor.length;j++) {
  sheet.removeEditor(vRemoveEditor[j][0])
}
}

} 

对于复选框

function onEdit(e){
  if (e.range.columnStart == 6 && e.range.columnEnd == 6 && e.range.rowStart <= 20) {
    var ckeckboxRange = "F1:F20";
    var date = new Date();
    var range = e.source.getRange(ckeckboxRange);
    var values = range.getValues().map(function(e) {return e[0] === true ? [date] : [""]});
    range.offset(0, 1).setValues(values);
  }
}

var SpreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var editors = SpreadSheet.getEditors();
for (var i = 0; i < editors.length; i++) {
     SpreadSheet.removeEditor(editors[i]);
    };

最后我们得到了预期的结果,因为它会更清楚地描述我所描述的内容。它就像一个命令门户,可以从整体上控制不同的访问权限。

Expected outcome

非常感谢所有有用的评论。

您需要以下组件:

  • onEdit 触发器
  • 检查哪个复选框已被编辑并连接到相应的 sheet
  • 从带有复选框的行中检索编辑器
  • 验证复选框是否已选中或未选中

下面是提供此功能的示例:

function onEdit(e){
  var ss = SpreadsheetApp.getActive();
  //change name of the sheet if necessary!
  var sheetWithCheckBoxes = ss.getSheetByName("Sheet1");
  var column =  e.range.getColumn();
  if (e.range.getSheet().getName() == sheetWithCheckBoxes.getName() && (column == 3 || column == 4 || column == 5)) {
    Logger.log("if");
    var spreadsheet2 = SpreadsheetApp.openById("XXX");
    var sheet;
    switch (column){
      case 3:
        sheet = ss.getSheetByName("name");
        break;
      case 4:
        sheet = ss.getSheetByName("name2");
        break;
      case 5:
        sheet = spreadsheet2.getSheetByName("name3");
        break;
    }       
   
    var protection = sheet.protect();
    if (protection.canDomainEdit()) {
      protection.setDomainEdit(false);
    }
    var editor = sheetWithCheckBoxes.getRange(e.range.getRow(), 2).getValue();
     Logger.log(e.value);
    if(e.value == "TRUE"){
       Logger.log("true");
      protection.addEditor(editor);
    }
    if(e.value == "FALSE"){
            Logger.log("false");
      protection.removeEditor(editor);
    }
  }
}

注:
在此示例中,前两个 sheet 与带有复选框的 sheet 处于相同的分布 sheet 中,而第三个 dsheet 处于不同的分布 sheet.

请根据您的需要调整sheet和传播sheet。

更新

既要设置sheet保护,又要与新用户分享传播sheet,需要使用方法DriveApp.getFileById(id).addEditor(editor).

但是,DriveApp.getFileById(id) 是一个无法通过简单的 onEdit 触发器触发的调用,原因是 restrictions

解法:

Bind an installable onEdit trigger 到你的函数而不是简单的函数。确保事先重命名函数以避免因为同时触发简单且可安装的触发器而发生冲突。

设置传播sheet 和sheet 权限的示例:

function Edit(e){
  var ss = SpreadsheetApp.getActive();
  //change name of the sheet if necessary!
  var sheetWithCheckBoxes = ss.getSheetByName("Sheet1");
  var column =  e.range.getColumn();
  if (e.range.getSheet().getName() == sheetWithCheckBoxes.getName() && (column == 3 || column == 4 || column == 5)) {
    var spreadsheet2 = SpreadsheetApp.openById("XXX");
    var sheet;
    var id;
    switch (column){
      case 3:
        sheet = ss.getSheetByName("name");
        id = ss.getId();
        break;
      case 4:
        sheet = ss.getSheetByName("name2");
        id = ss.getId();
        break;
      case 5:
        id = spreadsheet2.getId();
        sheet = spreadsheet2.getSheetByName("name3");
        break;
    }       
    var protection = sheet.protect();
    if (protection.canDomainEdit()) {
      protection.setDomainEdit(false);
    }
    var editor = sheetWithCheckBoxes.getRange(e.range.getRow(), 2).getValue();
    Logger.log(e.value);
    if(e.value == "TRUE"){
      DriveApp.getFileById(id).addEditor(editor);
      protection.addEditor(editor);
    }
    if(e.value == "FALSE"){
      protection.removeEditor(editor);
    }
  }
}