简体   繁体   中英

GAS Script : Is it possible to prevent simultaneous user?

just two questions:

I have a spreadsheet file editable by multiple user. but I'm afraid it will be annoying: first question: does an onOpen script run when a user opens a file while another user is editing it? (because my onOpen script resets some cells, so it could be annoying). So second question: is it possible to simply warn the user, when he tries to open the file, that it is already opened by another user and deny him access?

Thank you for your answers (I already search some answers whithout success)

Loïc

Does an onOpen script run when a user opens a file while another user is editing it?

Yes it will run. According to the official documentation :

The onOpen(e) trigger runs automatically when a user opens a spreadsheet, document, presentation, or form that they have permission to edit.

Is it possible to simply warn the user, when he tries to open the file, that it is already opened by another user and deny him access?

No, but what you can do is to use LockService which:

Prevents concurrent access to sections of code. This can be useful when you have multiple users or processes modifying a shared resource and want to prevent collisions.

There are many resources on how to use LockService and the solutions depends on your specific use case, so I would advice you to look for these resources, do some research and then ask a specific question regarding that if you are not able to implement it yourself.

Resources:

How to understand LockService and implement it correctly?

You can also consider using Properties Service which stores simple data in key-value pairs scoped to one script (Script Properties), one user of a script (User Properties), or one document (Document Properties).

I decided to use this Properties Service because your main concern is to prevent the execution of onOpen() which modifies some cells when there is someone already using the file. It is somewhat different with Lock Service , since lock service prevents simultaneous/concurrent execution of a code block.

Sample Implementation:

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);
}

How it works?

  1. When the file was opened, it will create a custom menu for file lock/unlock. Then check if there is an existing key in the script properties.

  2. If key exist, it will not implement the procedure for setting cell values and will show an alert message. If key doesn't exist, then it will execute the procedure and will ask the current user to lock the file.

I cannot lock the file automatically during onOpen() because during file open, Session.getActiveUser().getEmail() returns an empty string. You can either ask the current user to lock the file using the custom menu or create a prompt dialog and ask for the current user's email as the key value.

  1. You can lock/unlock the file using the custom menu. During file lock, it will check if there is no existing key before locking the file. While during the file unlock, it will check if the current user unlocking the file is the same person who locked the file before unlocking.

You can modify the alert messages based on your preference. This is just a guide on how you could use Properties Service in your goals.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM