GAS 脚本:是否可以防止同时使用?

问题描述

只有两个问题:

我有一个可由多个用户编辑的电子表格文件。但恐怕会很烦人: 第一个问题:当一个用户打开一个文件而另一个用户正在编辑它时,onopen 脚本会运行吗? (因为我的 onopen 脚本重置了一些单元格,所以它可能很烦人)。 那么第二个问题:是否可以在用户尝试打开文件时简单地警告用户文件已被另一个用户打开并拒绝他访问?

谢谢你的回答(我已经搜索了一些没有成功的答案)

洛伊克

解决方法

当一个用户打开一个文件而另一个用户正在编辑它时,onOpen 脚本是否运行?

是的,它会运行。根据{{​​3}}:

onOpen(e) 触发器在用户打开一个 他们拥有许可的电子表格、文档、演示文稿或表单 编辑。

是否可以在用户尝试打开文件时简单地警告用户该文件已被其他用户打开并拒绝他访问?

不,但您可以使用 official documentation 其中:

防止对代码段的并发访问。这很有用 当您有多个用户或进程修改共享资源时 并希望防止碰撞。

关于如何使用 LockService 的资源有很多,解决方案取决于您的具体用例,因此我建议您查找这些资源,做一些研究,然后提出一个具体的问题,如果您自己无法实现。

资源:

LockService

,

您还可以考虑使用 Properties Service 以键值对的形式存储简单数据,范围限定为一个脚本(脚本属性)、脚本的一个用户(用户属性)或一个文档(文档属性)。

我决定使用这个 Properties Service 是因为您主要关心的是防止执行 onOpen() 当有人已经在使用该文件时修改某些单元格。与 Lock Service 有所不同,因为锁服务会阻止代码块的同时/并发执行。

示例实现:

function onOpen(e){
  var ui = SpreadsheetApp.getUi();
  // Or DocumentApp or FormApp.
  ui.createMenu('LockFile')
      .addItem('Lock','lock')
      .addItem('Unlock','unlock')
      .addToUi();

  //Check if file is locked. if not,execute the procedure
  var scriptProperties = PropertiesService.getScriptProperties();
  var keys = scriptProperties.getKeys();
  if(keys.length==0){
    //Lock the file 
    //lock(); empty Session.getActiveUser().getEmail() received when user opens the spreadsheet
    showAlert("Please lock the file first");
    
    SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange('A1').setValue(Session.getActiveUser().getEmail());
    SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange('B1').setValue("Test");
  }else{
    showAlert("File is currenly locked by "+scriptProperties.getProperty('user'));
  }
}

function lock(){
  var scriptProperties = PropertiesService.getScriptProperties();
  var userEmail;
  var keys = scriptProperties.getKeys();
  Logger.log(keys.length);

  if(keys.length==0){
    //Create new property with current user's email
    userEmail = Session.getActiveUser().getEmail();
    Logger.log(userEmail);
    scriptProperties.setProperties({user: userEmail});
    showAlert("File successfully locked by "+userEmail);
    
  }else{
    userEmail = scriptProperties.getProperty('user');
    showAlert("File is currenly locked by "+userEmail);
  }

}
function unlock(){
  var scriptProperties = PropertiesService.getScriptProperties();
  var userEmail = Session.getActiveUser().getEmail();
  var keys = scriptProperties.getKeys();
  Logger.log(keys.length);
  Logger.log(scriptProperties.getProperty('user'));

  if(keys.length>0){
    Logger.log(scriptProperties.getProperty('user'));
    if(scriptProperties.getProperty('user') == userEmail){
      scriptProperties.deleteAllProperties();
      showAlert("File successfully unlocked by "+userEmail);
    }else{
      showAlert("File is currenly locked by "+scriptProperties.getProperty('user'));
    }
    
  }else{
    showAlert("File is not locked");
  }
}

function reset(){
  var scriptProperties = PropertiesService.getScriptProperties();
  scriptProperties.deleteAllProperties();
  showAlert("Lock has been reset");
}

function showAlert(message) {
  var ui = SpreadsheetApp.getUi(); // Same variations.
  Logger.log(message);
  var result = ui.alert(
     'File Lock',message,ui.ButtonSet.OK);
}

它是如何工作的?

  1. 当文件被打开时,它会创建一个用于文件锁定/解锁的自定义菜单。然后检查脚本属性中是否存在现有键。

  2. 如果key存在,它不会执行设置单元格值的过程,并会显示一条警告消息。如果key不存在,则执行程序并要求当前用户锁定文件。

我无法在 onOpen() 期间自动锁定文件,因为在文件打开期间,Session.getActiveUser().getEmail() 返回一个空字符串。您可以使用自定义菜单要求当前用户锁定文件,也可以创建一个 prompt dialog 并要求当前用户的电子邮件作为键值。

  1. 您可以使用自定义菜单锁定/解锁文件。在文件锁定期间,它会在锁定文件之前检查是否没有现有密钥。在文件解锁过程中,会检查当前解锁文件的用户是否与解锁前锁定文件的用户相同。

您可以根据自己的喜好修改警报消息。这只是关于如何在目标中使用 Properties Service 的指南。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...