[英]Google Sheets Apps Script On Edit Remove Editors From Protected Range Very Slow / Not Completing
I am relatively new to Google Apps Script and am having difficulties with my code below. 我是Google Apps脚本的新手,在下面的代码中遇到了困难。 Basically, it is bound to a sheet that acts as a workflow. 基本上,它绑定到充当工作流程的工作表。 I use the installed onEdit trigger, it loops through to see what cells have changed, then either timestamps, sends an email, or protects a range, given the cells that are changed. 我使用已安装的onEdit触发器,它会循环查看哪些单元格发生了更改,然后根据给定的单元格更改时间戳,发送电子邮件或保护范围。
I am running into the time stamp not always persisting, the email not always sending, and, the protection taking forever. 我遇到的时间戳记不总是持久存在,电子邮件也不是总是发送,并且保护永远存在。
Are there any more efficient ways to do this? 有没有更有效的方法来做到这一点?
function onEditFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
// CHECKS FOR CHANGE IN "UPDATES" SHEET ONLY
if (sheet.getSheetName() == "Updates") {
var activeRange = sheet.getActiveCell();
var activeRow = activeRange.getRow();
var activeColumn = activeRange.getColumn();
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Updates');
var sss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('LookUps');
var email = Session.getActiveUser().getEmail();
var timestamp = new Date();
var itemAttributes = sheet.getRange(activeRow, 1,activeRow,19).getValues();
// CHECKS FOR CHANGE IN ITEM COLUMN (A)
// if column A clear out the other cells
if (activeColumn == 1) {
var r = sheet.getActiveRange();
// CHECKS IF NUMBER OF ROWS INDICATES A PASTED RANGE
// if pasted range is more than one row in size, then loop through and do validation on all impacted rows
if (r.getNumRows() > 1) {
SpreadsheetApp.getActiveSpreadsheet().toast('Updating.....please wait.', 'Status', -1);
var l = r.getNumRows()
sheet.getRange(activeRow, 2, l, 13).clearContent();
for (var x = 0; x < l; x++) {
var ac = activeRow + x
if(ss.getRange(ac, 1).getvalue != '') {
sheet.getRange(ac, 12).setValue(email);
}
ss.getRange(ac, 1).copyTo(sss.getRange('G1'), {contentsOnly:true})
var dynamicList = sss.getRange('G2:G15'); // set to your sheet and range
var arrayValues = dynamicList.getValues();
var rangeRule = SpreadsheetApp.newDataValidation().requireValueInList(arrayValues);
ss.getRange(ac, 2).setDataValidation(rangeRule); // set range to your range
//SpreadsheetApp.flush();
var NewItemCheck = sss.getRange('G2').getValues()
if (NewItemCheck == "" && ss.getRange(ac, 1).getvalue != '') {
sheet.getRange(ac, 10).setValue("NEW ITEM")
}
} // END FOR LOOP THROUGH ROWS OF RANGE
SpreadsheetApp.getActiveSpreadsheet().toast('DONE', 'Status', 2);
} // END IF RANGE IS GREATER THAN 1 ROW
else
{
sheet.getRange(activeRow, 2, 1, 13).clearContent();
if(itemAttributes[0][0] != '') {
sheet.getRange(activeRow, 12).setValue(email);
}
sss.getRange('G1').setValue(itemAttributes[0][0]);
var dynamicList = sss.getRange('G2:G15');
var arrayValues = dynamicList.getValues();
var rangeRule = SpreadsheetApp.newDataValidation().requireValueInList(arrayValues);
ss.getRange(activeRow, 2).setDataValidation(rangeRule);
//SpreadsheetApp.flush();
var NewItemCheck = sss.getRange('G2').getValues()
if (NewItemCheck == "" && itemAttributes[0][0] != '') {
sheet.getRange(activeRow, 10).setValue("NEW ITEM")
}
}
}
// CHANGE IN Vendor Name / ID - LOC COLUMN (B)
if (activeColumn == 2) {
// if column B in Sheet UPDATES is changed, update adjacent drops downs
sheet.getRange(activeRow, 5).clearContent();
sss.getRange('H1').setValue(itemAttributes[0][1])
var dynamicList = sss.getRange('H2:H15');
var arrayValues = dynamicList.getValues();
var rangeRule = SpreadsheetApp.newDataValidation().requireValueInList(arrayValues);
ss.getRange(activeRow, 5).setDataValidation(rangeRule);
var a = itemAttributes[0][1].slice(-9);
var b = a.split(" ");
var c = itemAttributes[0][1].slice(-2);
var vendLocCombo = [[b,c]];
var vendLocComboRange = ss.getRange(activeRow, 3, 1, 2);
vendLocComboRange.setValues(vendLocCombo);
}
// SUBMITTED
if (activeColumn == 11 && itemAttributes[0][10] ){
// if column K in Sheet UPDATES is changed to TRUE (checked), email
// cost analysts in var CostEmail, and protect submitted info
sheet.getRange(activeRow, 13).setValue(timestamp);
SpreadsheetApp.flush();
var Prange = sheet.getRange('A'+activeRow+':M'+activeRow);
var protection = Prange.protect().setDescription('SubmitLock A'+activeRow+':M'+activeRow);
protection.removeEditors(protection.getEditors());
protection.addEditors(['emailhere.com','emailhere.com']);
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
}
// COMPLETED
if (activeColumn == 15 && itemAttributes[0][14]) {
// if column O in Sheet is changed to TRUE (checked) then user email and timestamp columns Q and R
sheet.getRange(activeRow, 17).setValue(email);
SpreadsheetApp.flush();
sheet.getRange(activeRow, 18).setValue(timestamp);
SpreadsheetApp.flush();
var Prange = sheet.getRange('N'+activeRow+':S'+activeRow);
var protection = Prange.protect().setDescription('CompleteLock N'+activeRow+':S'+activeRow);
protection.removeEditors(protection.getEditors());
protection.addEditors(['emailhere.com','emailhere.com']);
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
}
// DENIED
if (activeColumn == 16 && itemAttributes[0][15]) {
// if column P in Sheet is checked (true) send email to original submitter in column M
sheet.getRange(activeRow, 17).setValue(email);
sheet.getRange(activeRow, 18).setValue(timestamp);
var Prange = sheet.getRange('O'+activeRow+':T'+activeRow);
var protection = Prange.protect().setDescription('CompleteLock O'+activeRow+':T'+activeRow);
protection.removeEditors(protection.getEditors());
protection.addEditors(['emailhere.com','emailhere.com']);
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
var DeniedEmailAddress = itemAttributes[0][11];
var message = " Comments : "+itemAttributes[0][13];
var subject = "[Denied - Contracted Cost Request] "+itemAttributes[0][0];
MailApp.sendEmail(DeniedEmailAddress, subject, message,{
name: 'Contracted Cost Update',
attachments: []
});
sheet.getRange(activeRow, 19).setValue("X");
}
}
}
EDITS: 编辑:
function onEditFunction(e) {
if (e.source.getActiveSheet().getSheetName() == "Updates") {
// CHECKS FOR CHANGE IN "UPDATES" SHEET ONLY
var sheet = e.source.getActiveSheet();
var protectionDescription;
var protectedRange;
var i;
var protection;
var removeEditorsArray =
["group1@email.com","group2@email"];
var activeColumn = e.range.getColumn();
switch(activeColumn){
case 1: //Item
changeItem(e, sheet, activeColumn);
break;
case 2: //Vendor Name/ID - Loc
changeVendor(e, sheet, activeColumn);
break;
case 11: //SUBMIT check box
changeSubmit(e, sheet, activeColumn, protectionDescription, protectedRange, removeEditorsArray);
break;
case 15: //COMPLETE check box
changeComplete(e, sheet, activeColumn);
break;
case 16: //DENIED check box
changeDenied(e, sheet, activeColumn);
break;
}
}
}
function changeSubmit(e, sheet, activeColumn, protectionDescription, protectedRange, removeEditorsArray){
// if column K in Sheet UPDATES is changed to TRUE (checked), enter a timestamp and protect submitted info
var activeRow = e.range.getRow();
var timestamp = new Date();
var removeLen = removeEditorsArray.length
sheet.getRange(activeRow, 13).setValue(timestamp);
protectedRange = 'A'+activeRow+':M'+activeRow;
protectionDescription = 'SubmitLock A'+activeRow+':M'+activeRow;
protectRanges(sheet, protectionDescription, protectedRange, removeEditorsArray)
}
function protectRanges(sheet, protectionDescription, protectedRange, removeEditorsArray) {
var i=0;
var Len = removeEditorsArray.length;
protectedRange = sheet.getRange(protectedRange);
protectionDescription = protectedRange.protect().setDescription(protectionDescription);
for (i; i < Len; i++) {
protectionDescription.removeEditor(removeEditorsArray[i]);
}
}
Thanks to your help @tehhowch and @Vytautas, I was able to come up with a very efficient code, but did have to change the protection to a warning only, which is fine for the purposes of the sheet. 多亏了@tehhowch和@Vytautas的帮助,我才能够提出一个非常有效的代码,但确实必须将保护更改为仅警告,这对于工作表而言是很好的。
Please see below: 请看下面:
function onEditFunction(e) {
if (e.range.getSheet().getSheetName() == "Updates") {
// CHECKS FOR CHANGE IN "UPDATES" SHEET ONLY
var protectedRange;
var protectionDescription;
var sheet = e.range.getSheet();
var activeColumn = e.range.getColumn();
switch(activeColumn){
case 1: //Item
changeItem(e, sheet, activeColumn);
break;
case 2: //Vendor Name/ID - Loc
changeVendor(e, sheet, activeColumn);
break;
case 11: //SUBMIT check box
changeSubmit(e, sheet);
break;
case 15: //COMPLETE check box
changeComplete(e, sheet, activeColumn);
break;
case 16: //DENIED check box
changeDenied(e, sheet, activeColumn);
break;
}
}
}
function changeSubmit(e, sheet){
// if column K in Sheet UPDATES is changed to TRUE (checked), enter a timestamp and protect submitted info
var activeRow = e.range.getRow();
var timestamp = new Date();
var l = e.range.getNumRows();
if (l > 1){ // if pasted range is more than one row in size, then loop through and do validation on all impacted rows
SpreadsheetApp.getActiveSpreadsheet().toast('Updating.....please wait.', 'Status',-1);
}
for (var x = 0; x < l; x++) {
sheet.getRange(activeRow + x, 13).setValue(timestamp);
// SpreadsheetApp.flush();
protectedRange = 'A'+(activeRow + x) +':M'+(activeRow + x);
protectionDescription = 'SubmitLock A'+(activeRow + x)+':M'+(activeRow + x);
protectRanges(sheet, protectionDescription, protectedRange);
}
if (l > 1){ // if pasted range is more than one row in size, then loop through and do validation on all impacted rows
SpreadsheetApp.getActiveSpreadsheet().toast('DONE', 'Status',2);
}
}
function changeComplete(e, sheet, activeColumn){
// if column O in Sheet is changed to TRUE (checked) then user email and timestamp columns Q and R
var activeRow = e.range.getRow();
var newData = [];
var email = Session.getActiveUser().getEmail();
var timestamp = new Date();
newData = [[email],[timestamp]];
sheet.getRange(activeRow, 17, activeRow, 18).setValues(newData);
protectedRange = 'N'+activeRow+':S'+activeRow;
protectionDescription = 'CompleteLock N'+activeRow+':S'+activeRow;
protectRanges(sheet, protectionDescription, protectedRange);
}
function changeItem(e, sheet, activeColumn){
var activeRow = e.range.getRow();
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Updates');
var sss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('LookUps');
var email = Session.getActiveUser().getEmail();
var l = e.range.getNumRows();
var itemAttributes = sheet.getRange(activeRow, 1,(activeRow + l - 1),19).getValues();
if (l > 1){ // if pasted range is more than one row in size, then loop through and do validation on all impacted rows
SpreadsheetApp.getActiveSpreadsheet().toast('Updating.....please wait.', 'Status',-1);
}
for (var x = 0; x < l; x++) {
if(itemAttributes[x][0] != ''){
sheet.getRange(activeRow + x, 2,l, 13).clearContent(); // clears out row if new entry for item id
sheet.getRange(activeRow + x, 12).setValue(email); // stamps user in created by column
}
sss.getRange('G1').setValue(itemAttributes[x][0]);
var dynamicList = sss.getRange('G2:G15');
var arrayValues = dynamicList.getValues();
var rangeRule = SpreadsheetApp.newDataValidation().requireValueInList(arrayValues);
ss.getRange(activeRow + x,2).setDataValidation(rangeRule);
var NewItemCheck = sss.getRange('G2').getValues()
if (NewItemCheck == "" && itemAttributes[x][0] != '') {
sheet.getRange(activeRow + x, 10).setValue("NEW ITEM")
}
}
if (l > 1){ // if pasted range is more than one row in size, then loop through and do validation on all impacted rows
SpreadsheetApp.getActiveSpreadsheet().toast('DONE', 'Status',2);
}
}
function changeVendor(e, sheet, activeColumn){
// if column B in Sheet UPDATES is changed, update adjacent drops downs
var activeRow = e.range.getRow();
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Updates');
var sss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('LookUps');
var itemAttributes = sheet.getRange(activeRow, 1,activeRow,19).getValues();
sheet.getRange(activeRow, 5).clearContent();
sss.getRange('H1').setValue(itemAttributes[0][1])
var dynamicList = sss.getRange('H2:H15');
var arrayValues = dynamicList.getValues();
var rangeRule = SpreadsheetApp.newDataValidation().requireValueInList(arrayValues);
ss.getRange(activeRow,5).setDataValidation(rangeRule);
var a = itemAttributes[0][1].slice(-9);
var b = a.split(" ");
var c = itemAttributes[0][1].slice(-2);
var vendLocCombo = [[b,c]];
var vendLocComboRange = ss.getRange(activeRow, 3, 1, 2);
vendLocComboRange.setValues(vendLocCombo);
}
function changeDenied(e, sheet, activeColumn){
// if column P in Sheet is checked (true) send email to original submitter in column M
var activeRow = e.range.getRow();
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Updates');
var sss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('LookUps');
var email = Session.getActiveUser().getEmail();
var timestamp = new Date();
var itemAttributes = sheet.getRange(activeRow, 1,activeRow,19).getValues();
sheet.getRange(activeRow, 17).setValue(email);
sheet.getRange(activeRow, 18).setValue(timestamp);
protectedRange = 'N'+activeRow+':S'+activeRow;
protectionDescription = 'CompleteLock N'+activeRow+':S'+activeRow;
protectRanges(sheet, protectionDescription, protectedRange);
var DeniedEmailAddress = itemAttributes[0][11];
var message = " Comments : "+itemAttributes[0][13];
var subject = "[Denied - Contracted Cost Request] "+itemAttributes[0][0];
MailApp.sendEmail(DeniedEmailAddress, subject, message,{
name: 'Contracted Cost Update',
attachments: []
});
sheet.getRange(activeRow, 19).setValue("X");
}
function protectRanges(sheet, protectionDescription, protectedRange) {
protectedRange = sheet.getRange(protectedRange);
protectionDescription = protectedRange.protect().setDescription(protectionDescription);
protectionDescription.setWarningOnly(true);
SpreadsheetApp.flush();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.