首页 > 解决方案 > 如何删除或以编程方式禁用/阻止复制的 Google Doc 上的附加脚本?

问题描述

我正在寻找模拟 Google Classroom 作业功能的行为,该功能允许您为学生列表制作文档副本。此副本保留创建者的所有权,并将学生添加为编辑。

我已经使用附加到模板文档的脚本成功地完成了这项工作。教师可以将电子邮件地址列表粘贴到自定义拉出中,并在提交时循环创建具有权限的每个文档。

尝试:

有希望的解决方案:

我一直在兜圈子,最后一直在解释如何一次将一个元素复制到新文档中的帖子。由于格式化,这似乎还不够,所以我希望涉及保留该copy()功能的其他解决方案之一是可能的。

侧边栏代码 sidebar.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
    
    </script>
    <style>
    textarea{
    font-size: .9em;
    width: 90%;
    height: 300px;
    }
    </style>
  </head>
  <body>
  

<textarea id="addressList">
Paste class email list here with spaces between addresses.
</textarea>
<p>
<input id="submit" type="button" value="Distribute to Students" onclick="distributor();" />
<input id="reset" type="button" value="Reset" onclick="reset();" />

</p>

<script>

function reset(){
   document.getElementById('addressList').value = "Paste class email list here with spaces between addresses.";
   document.getElementById("submit").disabled = false;
}

var mainOut = "";

function cleanUp(output){
   mainOut += output;
   document.getElementById('addressList').value = mainOut;
}

function distributor(){
  document.getElementById("submit").disabled = true;
  
  var nameList = document.getElementById('addressList').value; // get email list
  var list = nameList.split("\n"); // break it up
  
  // loop through names
  for(let i = 0; i < list.length; i++){
     // create a doc for each student and return success to the UI
     google.script.run.withSuccessHandler(cleanUp).distro(list[i],i+1,list.length);
  }
}

</script>
</body>
</html>

当前脚本代码.gs

// student email addresses end in a 2 digit class year, faculty does not
var event;
var emailParts = Session.getEffectiveUser().getEmail().split('@');
var username = emailParts[0];
var classCheck = username.substring(username.length-2);
var validUser = false;

// using school email address style, determine if student or teacher to hide the UI changes
if(isNaN(classCheck)){
  validUser = true;
} 

// Custom  Menu
function onOpen(e){
  if(validUser){
    event = e;
    var ui = DocumentApp.getUi();
    var faMenu = ui.createMenu('FA')
    .addItem('Open Distribution Tool', 'openTool').addToUi();
  }
}

/**
* Creates Custom Sidebar for emailing teams from spreadsheet
*/
function openTool() {
  if(validUser){
    var html = HtmlService.createHtmlOutputFromFile('sidebar');
    html.setTitle('Share with Students');
    html.setWidth(400);
    html.setContent(html.getContent());
    DocumentApp.getUi().showSidebar(html);
  }
}

// create copy, set permissions
function distro(studentEmail,count,total){
  var output = "";
  if(validUser){
    
    var teacherEmail = 'xxx@xxx.org'; // this will be replaced by email of logged in user
    var thisDoc = DocumentApp.getActiveDocument();
    let studentName = studentEmail.split('@')[0];
      
    if(studentEmail != "" && studentEmail != null){
      
      let filename = thisDoc.getName() + "- " + studentName;
      let newDoc = DriveApp.getFileById(thisDoc.getId()).makeCopy(filename);
      
      newDoc.setOwner(studentEmail);
      newDoc.addEditor(teacherEmail);
      output += "Created doc " + count + "/" + total + ": " + filename + "\n";
    }
  }
  return output;
}

标签: google-apps-scriptgoogle-classroom

解决方案


问题:

我认为您不能以编程方式从复制的文档中删除绑定的脚本。

理论上,如果您使用Apps Script API,通过调用projects.updateContent并为您的Files设置和清空内容,这是可能的。

然而,这需要知道scriptId,并且您不能以编程方式检索scriptId不是当前脚本的绑定脚本(对于当前脚本,可以使用Session.getScriptId() )。例如,请参阅此答案以及此相关功能请求:

解决方法 - 使用库:

作为一种解决方法,我建议将至少一些脚本代码放在不同的独立脚本中,并让您的模板调用这个库。这样,绑定到复制文件的脚本将无法使用库源代码,该脚本只能运行库中定义的不同功能。

例如,您可以移动onOpendistro到另一个脚本:

图书馆代码.gs:

// student email addresses end in a 2 digit class year, faculty does not
var event;
var emailParts = Session.getEffectiveUser().getEmail().split('@');
var username = emailParts[0];
var classCheck = username.substring(username.length-2);
var validUser = false;

// using school email address style, determine if student or teacher to hide the UI changes
if(isNaN(classCheck)){
  validUser = true;
}

// Custom  Menu
function onOpen(e){
  if(validUser){
    event = e;
    var ui = DocumentApp.getUi();
    var faMenu = ui.createMenu('FA')
    .addItem('Open Distribution Tool', 'openTool').addToUi();
  }
}

// create copy, set permissions
function distro(studentEmail,count,total){
  var output = "";
  if(validUser){
    
    var teacherEmail = 'xxx@xxx.org'; // this will be replaced by email of logged in user
    var thisDoc = DocumentApp.getActiveDocument();
    let studentName = studentEmail.split('@')[0];
      
    if(studentEmail != "" && studentEmail != null){
      
      let filename = thisDoc.getName() + "- " + studentName;
      let newDoc = DriveApp.getFileById(thisDoc.getId()).makeCopy(filename);
      
      newDoc.setOwner(studentEmail);
      newDoc.addEditor(teacherEmail);
      output += "Created doc " + count + "/" + total + ": " + filename + "\n";
    }
  }
  return output;
}

然后,将此脚本作为库共享,并在您的模板脚本中使用它,可能是这样的(LIBRARY您之前共享的库的标识符在哪里):

模板代码.gs:

// student email addresses end in a 2 digit class year, faculty does not
var event;
var emailParts = Session.getEffectiveUser().getEmail().split('@');
var username = emailParts[0];
var classCheck = username.substring(username.length-2);
var validUser = false;

// using school email address style, determine if student or teacher to hide the UI changes
if(isNaN(classCheck)){
  validUser = true;
} 

// Custom  Menu
function onOpen(e){
  LIBRARY.onOpen(e);
}

/**
* Creates Custom Sidebar for emailing teams from spreadsheet
*/
function openTool() {
  if(validUser){
    var html = HtmlService.createHtmlOutputFromFile('sidebar');
    html.setTitle('Share with Students');
    html.setWidth(400);
    html.setContent(html.getContent());
    DocumentApp.getUi().showSidebar(html);
  }
}

// create copy, set permissions
function distro(studentEmail,count,total){
  LIBRARY.distro(studentEmail, count, total);
}

在此示例中,sidebar.html也将包含在您的模板脚本中。

笔记:

  • 这是一个基本示例,只是为了展示如何做到这一点,并且可能会得到改进。例如,即使调用via可能会变得棘手,也应该可以openTool将文件移动到库代码中:请参阅使用 google.script.run 从 html 调用库函数.htmldistrogoogle.script.run

参考:


推荐阅读