Google Apps脚本 - 编辑器在电子表格上执行脚本

时间:2013-11-05 19:18:57

标签: google-apps-script

我创建了一个Google电子表格,以帮助我的团队跟踪他们即将到来的一周的日历。电子表格有2个选项卡:“概览”选项卡和“详细信息”选项卡。在“详细信息”选项卡上,顶行列出了截至年末的所有工作日,左列列出了团队成员名称。对于每一天,团队成员都会写下他们将在哪所学校以及对支持的描述。

“概览”选项卡与“详细信息”选项卡具有相同的结构(即,顶部的日期和左侧列出的名称),但提供了每个人所在位置的可视摘要。我编写了一个脚本,该脚本从“详细信息”选项卡中获取学校名称,并将其输入到与“概述”选项卡上的正确人员/日期对应的单元格中。然后,它将获取支持的描述,并在“概述”选项卡上创建一个带有描述的注释。它还会对“概述”选项卡上的单元格进行着色,以便我可以看到计划提供支持。因此,从“概述”选项卡中,我所要做的就是将鼠标悬停在单元格上,它将向我显示计划的支持。

它在我自己的帐户中运作良好。但是,我与一些团队成员共享了电子表格,但它无法正常工作。我不希望我的团队能够编辑“概述”选项卡,因为我只希望他们在“详细信息”选项卡上输入他们的信息。如果我给他们“概述”选项卡的编辑权限,那么他们可以更改注释,单元格颜色,工作表结构等(这就是我希望“概览”选项卡为仅查看的原因)。因此,我保护了“概览”标签,因此无法进行修改。但是,由于无法编辑此工作表,因此在编辑“详细信息”选项卡时,脚本似乎不会运行并更新“概述”选项卡。我认为这是因为他们没有权限(因为表格受到保护)。当我删除表单保护时,脚本运行正常。

关于如何解决这个问题的任何想法?我真的需要保持Overview选项卡View-only。感谢。

4 个答案:

答案 0 :(得分:4)

正如您在评论中所述,您使用安装在编辑触发器上时,您描述的问题不会发生,因为“当脚本运行时因为触发器,脚本使用安装触发器的人员的身份运行,而不是操作触发事件的用户的身份。这是出于安全原因。例如,如果您在脚本中安装触发器,但是您的同事执行触发事件的操作,脚本以您的身份运行,而不是您的同事的身份。有关此信息的完整信息,请参阅了解权限和脚本执行。“

请参阅文档here


编辑:抱歉,我没有看到有关此特殊情况的问题:issue 1562 posted on july 2012, status "triaged"


编辑2:我尝试@tracon6建议暂时删除保护但它也不起作用...脚本在尝试应用保护时会产生错误。

作为编辑3

我发现了一个有效的解决方法!我们可以只为我们写入targetSheet的时间添加一个编辑器,然后立即将其删除......在它之间使用flush

这是我用来测试的代码:

function onEditInstallable(event) {
  var sheet = event.source.getActiveSheet();
  if(sheet.getName()=='Sheet1'){return};
  var r = event.source.getActiveRange();
  var column = r.getColumn();
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var targetSheet = ss.getSheetByName("TFA");
  var targetSheet = ss.getSheetByName("Sheet1");
  var user = SpreadsheetApp.getActive().getEditors()[1];
  var permission = targetSheet.getSheetProtection();
  permission.addUser(user);
  targetSheet.setSheetProtection(permission);
  SpreadsheetApp.flush();
  targetSheet.getRange(1,column).setValue('value change on sheet 2, column  : '+column);
  SpreadsheetApp.flush();
  permission.removeUser(user)
  targetSheet.setSheetProtection(permission)
}

编辑4:

由于许多编辑似乎可以访问这些工作表(请参阅上一条评论),因此必须有一种方法可以了解电子表格中的哪些人是活跃的。在非域环境中,使用触发函数是不可能的,因此我建议使用一个小的uiApp,其中包含用户必须选择的列表,使用可安装的onOpen触发该值并存储该值以在主函数中使用它。 / p>

Heres是处理这方面的一段代码。

function SpecialonOpen(){
  var s = SpreadsheetApp.getActive();
  var app = UiApp.createApplication().setTitle('Please select your email in this list').setWidth(300).setHeight(300);
  var list = app.createListBox().setName('list')
  var editors = s.getEditors();
  for(var n in editors){
    list.addItem(editors[n].getEmail());
  }
  var handler = app.createServerHandler('getMail').addCallbackElement(list);
  var btn = app.createButton('select',handler);
  s.show(app.add(list).add(btn))
}

function getMail(e){
  var email = e.parameter.list;
  var editors = ScriptProperties.getProperty('currentEditors')||' ';
  if(editors.indexOf(email)==-1){
    editors+=(','+email);
  ScriptProperties.setProperty('currentEditors',editors);
  }
  var app = UiApp.getActiveApplication().close();
  var editors = ScriptProperties.getProperty('currentEditors').split(',');
  if(editors[0].length<2){editors.splice(0,1)};
  Logger.log(editors)
  return app
}

enter image description here

您还应该添加一个功能,以便在某个时刻重置此列表...不知道什么是最好的?在每日基地可能吗?我会告诉你的; - )

答案 1 :(得分:1)

“概览”标签和“详细信息”标签是否需要位于同一电子表格中?

也许您可以在电子表格中使用“概览”标签,只有您可以访问并在其他人都可以访问的电子表格中包含“详细信息”标签 - 然后您可以修改脚本以使用新“详细信息电子表格”中的信息更新新的“概述电子表格”。

或者,在脚本中,您可以关闭“概述”选项卡上的保护,然后运行脚本的主要部分,然后在脚本结束之前再次打开“概述”选项卡上的保护(请参阅https://developers.google.com/apps-script/reference/spreadsheet/page-protection#setProtected(Boolean)

不可否认,这些选项都不像onEdit选项一样干净。

答案 2 :(得分:0)

这是一个可以尝试的hacky workarround:将脚本作为具有匿名访问权限的内容服务发布,并使用触发器中的urlFetch调用它,将必要的param传递给您的服务。 这应该导致代码在有效用户是脚本发布者而不是用户的不同上下文中执行。你会慢一些。

答案 3 :(得分:0)

为什么不使用“数据”标签中的选项保护“概览”工作表,并将“编辑”权限设置为“仅限您”。这样可以保护工作表免受所有人,甚至编辑的影响,使工作表处于“仅查看”模式,除了您自己以外的所有人。