Collecting a Gmail Username when a Button is Pressed In Google Sheets - google-apps-script

I am creating a bathroom sign out sheet for my middle school students. I have created a Google App Script that Collects students names from a dropdown box and then logs the date and time. Everything seems to work great except when 500 students have access to the sheet at the same time. If a student selects their name it can possibly change before the script can be run. I would like to replace the dropdown box with a script that will automatically grab their Google User Name. Is there anyway this can be done? I am a novice programmer and tend to get things to work by tinkering around with it, but this seems to be above my head. Here is the Google Sheet and the Script is attached as well. Thanks in advance
https://docs.google.com/spreadsheets/d/e/2PACX-1vR36FnMTbJV4Nl8X8x_VyG107Y8Q-oCSgfG3ITEvaMjSraMv-bUH2u4FuWSE74Qg1gCrO5bg12pvawe/pubhtml
function clockIn()
{
//DEFINE ALL ACTIVE SHEETS
var ss = SpreadsheetApp.getActiveSpreadsheet();
//DEFINE MAIN SHEET
var mainSheet = ss.getSheetByName("DATASHEET");
//LAST ROW ON MAIN SHEET
var lastRow = mainSheet.getLastRow();
for (var j = 5; j <= lastRow; j++)
{
// CHECK CLOCK IN
if(mainSheet.getRange('B1:B1').getValue() == mainSheet.getRange(j, 1).getValue() && mainSheet.getRange(j,3).getValue() == '')
{
Browser.msgBox("⚠️ You are Already Signed Out","Please Click the Returning to Classroom Button and then Try Again!",Browser.Buttons.OK);
return;
}
}
//_________________________________________________________________________________________________________________________________________________//
// ADD CLOCK IN RECORD
mainSheet.getRange(lastRow+1,1).setValue(mainSheet.getRange('B1:B1').getValue()).setFontSize(12);
mainSheet.getRange(lastRow+1,2).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss A/P").setHorizontalAlignment("left").setFontSize(12);
//CLEARCONTENTS
{
var sheet = ss.getSheetByName("MAIN");
sheet.getRange('B1:B2').clearContent();
}
if (mainSheet.getRange('B1:B1').getValue() == mainSheet.getRange('B1:B1').getValue() && mainSheet.getRange(j,3).getValue() == '')
{
SpreadsheetApp.getUi().alert("⏰ Please Hurry Back! ⏰","Your Teacher is Waiting",SpreadsheetApp.getUi().ButtonSet.OK);
}
}
//_________________________________________________________________________________________________________________________________________________//
function clockOut() {
//DEFINE ALL ACTIVE SHEETS
var ss = SpreadsheetApp.getActiveSpreadsheet();
//DEFINE MAIN SHEET
var mainSheet = ss.getSheetByName("DATASHEET");
//LAST ROW ON MAIN SHEET
var lastRow = mainSheet.getLastRow();
var foundRecord = false;
for (var j = 5; j <= lastRow; j++)
{
// FIND CLOCK IN RECORD
if(mainSheet.getRange('B1:B1').getValue() == mainSheet.getRange(j, 1).getValue() && mainSheet.getRange(j,3).getValue() == '')
{
SpreadsheetApp.getUi().alert("🙏 Thank You! 🙏"," " ,SpreadsheetApp.getUi().ButtonSet.OK);
// UPDATE CLOCK IN RECORD
mainSheet.getRange(j,3).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss A/P").setHorizontalAlignment("left").setFontSize(12);
var totalTime = (mainSheet.getRange(j,3).getValue() - mainSheet.getRange(j,2).getValue()) /(60*100*1000);
mainSheet.getRange(j,4).setValue(totalTime.toFixed(2)).setNumberFormat("#0.00").setHorizontalAlignment("left").setFontSize(12);
foundRecord = true;
}
}
//CLEARCONTENTS
{
var sheet = ss.getSheetByName("MAIN");
sheet.getRange('B1:B2').clearContent();
}
// IF NO CLOCK IN RECORD
if(foundRecord == false)
{
SpreadsheetApp.getUi().alert("⚠️ No Record ⚠️","You Might Have Forget to Sign Out?" ,SpreadsheetApp.getUi(). ButtonSet.OK);
}
}
//_________________________________________________________________________________________________________________________________________________//
// CALL TOTAL HOURS
TotalHours();
function TotalHours()
{
//DEFINE ALL ACTIVE SHEETS
var ss = SpreadsheetApp.getActiveSpreadsheet();
//DEFINE MAIN SHEET
var mainSheet = ss.getSheetByName("DATASHEET");
//LAST ROW ON MAIN SHEET
var lastRow = mainSheet.getLastRow();
//DEFINE ARRAY
var totals = [];
//LOOP THROUGH ALL RATES
for (var j = 5; j <= lastRow; j++)
{
var rate = mainSheet.getRange(j, 4).getValue();
var name = mainSheet.getRange(j, 1).getValue();
var foundRecord = false;
for(var i = 0; i < totals.length; i++)
{
//FOUND RECORD ADD TO TOTAL
if(name == totals[i][0] && rate != '')
{
totals[i][1] = totals[i][1] + rate;
foundRecord = true;
}
}
//ADD NEW RECORD, EXISTING RECORD NOT FOUND
if(foundRecord == false && rate != '')
{
totals.push([name, rate]);
}
}
//CLEAR DATA
mainSheet.getRange("F5:G1000").clear();
//DISPLAY TOTALS
for(var i = 0; i < totals.length; i++)
{
mainSheet.getRange(5+i,6).setValue(totals[i][0]).setFontSize(12);
mainSheet.getRange(5+i,7).setValue(totals[i][1]).setFontSize(12);
}
}
//_________________________________________________________________________________________________________________________________________________//
function ClearCells()
{
var sheet = SpreadsheetApp.getActive().getSheetByName('DATASHEET');
sheet.getRange('A5:G1000').clearContent();
}
//_________________________________________________________________________________________________________________________________________________//
function clearRange()
{
// replace 'Sheet1' with your actual sheet name
// replace 'dhrhrejYOURSHETIDerhe5j54j5j' with your actual sheet ID
var sheetActive = SpreadsheetApp.openById("1sjx0UAv73wiW-Jo1e8QWZuanjKK2tsjveVXjB1y_IHw").getSheetByName("DATASHEET");
sheetActive.getRange('A5:G1000').clearContent();
}
//_________________________________________________________________________________________________________________________________________________//
``

This works for me:
function getUserEmail() {
SpreadsheetApp.getActive().toast(Session.getActiveUser().getEmail());
}
But it may not work all of the time because of a complex set of security protocols which I know nothing about.

Since you are pertaining to the email address of the user, you can use Session.getActiveUser() which will give you the current user, then use getEmail() to get the current user's email address. Similar to what #Cooper suggested
You just need to use them in your clockIn() and clockOut():
function clockIn()
{
//DEFINE ALL ACTIVE SHEETS
var ss = SpreadsheetApp.getActiveSpreadsheet();
//DEFINE MAIN SHEET
var mainSheet = ss.getSheetByName("DATASHEET");
//LAST ROW ON MAIN SHEET
var lastRow = mainSheet.getLastRow();
for (var j = 5; j <= lastRow; j++)
{
// CHECK CLOCK IN
if(Session.getActiveUser().getEmail() == mainSheet.getRange(j, 1).getValue() && mainSheet.getRange(j,3).getValue() == '')
{
Browser.msgBox("⚠️ You are Already Signed Out","Please Click the Returning to Classroom Button and then Try Again!",Browser.Buttons.OK);
return;
}
}
//_________________________________________________________________________________________________________________________________________________//
// ADD CLOCK IN RECORD
mainSheet.getRange(lastRow+1,1).setValue(Session.getActiveUser().getEmail()).setFontSize(12);
mainSheet.getRange(lastRow+1,2).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss A/P").setHorizontalAlignment("left").setFontSize(12);
//CLEARCONTENTS
{
var sheet = ss.getSheetByName("MAIN");
sheet.getRange('B1:B2').clearContent();
}
if (Session.getActiveUser().getEmail() == Session.getActiveUser().getEmail() && mainSheet.getRange(j,3).getValue() == '')
{
SpreadsheetApp.getUi().alert("⏰ Please Hurry Back! ⏰","Your Teacher is Waiting",SpreadsheetApp.getUi().ButtonSet.OK);
}
}
//_________________________________________________________________________________________________________________________________________________//
function clockOut() {
//DEFINE ALL ACTIVE SHEETS
var ss = SpreadsheetApp.getActiveSpreadsheet();
//DEFINE MAIN SHEET
var mainSheet = ss.getSheetByName("DATASHEET");
//LAST ROW ON MAIN SHEET
var lastRow = mainSheet.getLastRow();
var foundRecord = false;
for (var j = 5; j <= lastRow; j++)
{
// FIND CLOCK IN RECORD
if(Session.getActiveUser().getEmail() == mainSheet.getRange(j, 1).getValue() && mainSheet.getRange(j,3).getValue() == '')
{
SpreadsheetApp.getUi().alert("🙏 Thank You! 🙏"," " ,SpreadsheetApp.getUi().ButtonSet.OK);
// UPDATE CLOCK IN RECORD
mainSheet.getRange(j,3).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss A/P").setHorizontalAlignment("left").setFontSize(12);
var totalTime = (mainSheet.getRange(j,3).getValue() - mainSheet.getRange(j,2).getValue()) /(60*100*1000);
mainSheet.getRange(j,4).setValue(totalTime.toFixed(2)).setNumberFormat("#0.00").setHorizontalAlignment("left").setFontSize(12);
foundRecord = true;
}
}
//CLEARCONTENTS
{
var sheet = ss.getSheetByName("MAIN");
sheet.getRange('B1:B2').clearContent();
}
// IF NO CLOCK IN RECORD
if(foundRecord == false)
{
SpreadsheetApp.getUi().alert("⚠️ No Record ⚠️","You Might Have Forget to Sign Out?" ,SpreadsheetApp.getUi(). ButtonSet.OK);
}
}
//_____
Another option is to use promt dialog to ask user to input their name when clockIn() or clockOut() was called. Then change the inputted name to capital letters.
Your Code:
function clockIn()
{
//DEFINE ALL ACTIVE SHEETS
var ss = SpreadsheetApp.getActiveSpreadsheet();
//DEFINE MAIN SHEET
var mainSheet = ss.getSheetByName("DATASHEET");
//LAST ROW ON MAIN SHEET
var lastRow = mainSheet.getLastRow();
var ui = SpreadsheetApp.getUi();
var response = ui.prompt('Enter your name:',ui.ButtonSet.OK_CANCEL);
var studentName;
// Process the user's response.
if (response.getSelectedButton() == ui.Button.OK) {
Logger.log('The user\'s name is %s.', response.getResponseText());
studentName = studentName.toUpperCase();
studentName = response.getResponseText();
} else {
Logger.log('Request was cancelled.');
return;
}
for (var j = 5; j <= lastRow; j++)
{
// CHECK CLOCK IN
if(studentName == mainSheet.getRange(j, 1).getValue() && mainSheet.getRange(j,3).getValue() == '')
{
Browser.msgBox("⚠️ You are Already Signed Out","Please Click the Returning to Classroom Button and then Try Again!",Browser.Buttons.OK);
return;
}
}
//_________________________________________________________________________________________________________________________________________________//
// ADD CLOCK IN RECORD
mainSheet.getRange(lastRow+1,1).setValue(studentName).setFontSize(12);
mainSheet.getRange(lastRow+1,2).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss A/P").setHorizontalAlignment("left").setFontSize(12);
//CLEARCONTENTS
{
var sheet = ss.getSheetByName("MAIN");
sheet.getRange('B1:B2').clearContent();
}
if (studentName == studentName && mainSheet.getRange(j,3).getValue() == '')
{
SpreadsheetApp.getUi().alert("⏰ Please Hurry Back! ⏰","Your Teacher is Waiting",SpreadsheetApp.getUi().ButtonSet.OK);
}
}
//_________________________________________________________________________________________________________________________________________________//
function clockOut() {
//DEFINE ALL ACTIVE SHEETS
var ss = SpreadsheetApp.getActiveSpreadsheet();
//DEFINE MAIN SHEET
var mainSheet = ss.getSheetByName("DATASHEET");
//LAST ROW ON MAIN SHEET
var lastRow = mainSheet.getLastRow();
var foundRecord = false;
var ui = SpreadsheetApp.getUi();
var response = ui.prompt('Enter your name:',ui.ButtonSet.OK_CANCEL);
var studentName;
// Process the user's response.
if (response.getSelectedButton() == ui.Button.OK) {
Logger.log('The user\'s name is %s.', response.getResponseText());
studentName = response.getResponseText();
studentName = studentName.toUpperCase();
} else {
Logger.log('Request was cancelled.');
return;
}
for (var j = 5; j <= lastRow; j++)
{
// FIND CLOCK IN RECORD
if(studentName == mainSheet.getRange(j, 1).getValue() && mainSheet.getRange(j,3).getValue() == '')
{
SpreadsheetApp.getUi().alert("🙏 Thank You! 🙏"," " ,SpreadsheetApp.getUi().ButtonSet.OK);
// UPDATE CLOCK IN RECORD
mainSheet.getRange(j,3).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss A/P").setHorizontalAlignment("left").setFontSize(12);
var totalTime = (mainSheet.getRange(j,3).getValue() - mainSheet.getRange(j,2).getValue()) /(60*100*1000);
mainSheet.getRange(j,4).setValue(totalTime.toFixed(2)).setNumberFormat("#0.00").setHorizontalAlignment("left").setFontSize(12);
foundRecord = true;
}
}
//CLEARCONTENTS
{
var sheet = ss.getSheetByName("MAIN");
sheet.getRange('B1:B2').clearContent();
}
// IF NO CLOCK IN RECORD
if(foundRecord == false)
{
SpreadsheetApp.getUi().alert("⚠️ No Record ⚠️","You Might Have Forget to Sign Out?" ,SpreadsheetApp.getUi(). ButtonSet.OK);
}
}
//_____

Related

How to allow non-sheet owners run scripts that involve protected cells

I have the script below where some cells are protected because they contain formula but I can script linked to buttons that when executed, it updates the cell values in these protected cells, this is fine if you are the sheet owner but if you are not you get a error saying 'You are editing protected cells....'
I have seen some solutions where the script has been deployed as a web app and then set so it always runs as the owner but can't get this working for my use case, I deployed and set as to always run as me but this only seems like half the solution?
My code is below:
//
// Save Data
function submitData() {
var SPREADSHEET_NAME = "Data";
var SEARCH_COL_IDX = 0;
var RETURN_COL_IDX = 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
var datasheet = ss.getSheetByName("Data"); //Data Sheet
var str = formSS.getRange("A10").getValue();
var values = ss.getSheetByName(SPREADSHEET_NAME).getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] != str ) {
//SpreadsheetApp.getUi().alert(' "Dmp #' + formSS.getRange("A4").getValue() + ' "');
// return row[RETURN_COL_IDX];
//} else {
//Input Values
var values1 = [[formSS.getRange("A10").getValue(),
formSS.getRange("B10").getValue(),
formSS.getRange("C10").getValue(),
formSS.getRange("D10").getValue(),
formSS.getRange("E10").getValue(),
formSS.getRange("F10").getValue(),
formSS.getRange("G10").getValue(),
formSS.getRange("H10").getValue(),
formSS.getRange("I10").getValue(),
formSS.getRange("J10").getValue(),
formSS.getRange("K10").getValue()]];
var values2 = [[formSS.getRange("A10").getValue(),
formSS.getRange("B10").getValue(),
formSS.getRange("C10").getValue(),
formSS.getRange("D10").getValue(),
formSS.getRange("E10").getValue(),
formSS.getRange("F10").getValue(),
formSS.getRange("G10").getValue(),
formSS.getRange("I10").getValue(),
formSS.getRange("J10").getValue(),
formSS.getRange("K10").getValue()]];
values2[0].forEach(function(val) {
if (val === "") {
throw new Error("Please fill in Project, Category, Subsystem, Description and Created By Fields.");
}
})
// Save New Data
datasheet.getRange(datasheet.getLastRow()+1, 1, 1, 11).setValues(values1);
SpreadsheetApp.getUi().alert(' New Record Created ');
formSS.getRange("D10").clearContent();
formSS.getRange("E10").clearContent();
formSS.getRange("F10").clearContent();
formSS.getRange("G10").clearContent();
formSS.getRange("H10").clearContent();
formSS.getRange("I10").clearContent();
formSS.getRange("J10").setValue(new Date())
return row[RETURN_COL_IDX];
}
}
}
//=========================================================
// Clear form
function clearCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
formSS.getRange("D10").clearContent();
formSS.getRange("E10").clearContent();
formSS.getRange("F10").clearContent();
formSS.getRange("G10").clearContent();
formSS.getRange("I10").clearContent();
formSS.getRange("J10").setValue(new Date())
return true ;
}
//=====================================================================
var SPREADSHEET_NAME = "Data";
var SEARCH_COL_IDX = 0;
var RETURN_COL_IDX = 0;
function searchStr() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
var str = formSS.getRange("F4").getValue();
var values = ss.getSheetByName(SPREADSHEET_NAME).getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] == str) {
formSS.getRange("A6").setValue(row[0]) ;
formSS.getRange("B6").setValue(row[1]);
formSS.getRange("C6").setValue(row[2]);
formSS.getRange("D6").setValue(row[3]);
formSS.getRange("E6").setValue(row[4]);
formSS.getRange("F6").setValue(row[5]);
formSS.getRange("G6").setValue(row[6]);
formSS.getRange("H6").setValue(row[7]);
formSS.getRange("I6").setValue(row[8]);
formSS.getRange("J6").setValue(row[9]);
return row[RETURN_COL_IDX];
}
}
}
//===================================================================
function rowDelete() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
var datasheet = ss.getSheetByName("Data"); //Data Sheet
var ui = SpreadsheetApp.getUi();
var response = ui.alert(
'Are you sure you want to delete this record?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
var str = formSS.getRange("F4").getValue();
var values = ss.getSheetByName(SPREADSHEET_NAME).getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] == str) {
var INT_R = i+1
datasheet.deleteRow(INT_R) ;
formSS.getRange("A6").clearContent();
formSS.getRange("B6").clearContent();
formSS.getRange("C6").clearContent();
formSS.getRange("D6").clearContent();
formSS.getRange("E6").clearContent();
formSS.getRange("F6").clearContent();
formSS.getRange("G6").clearContent();
formSS.getRange("H6").clearContent();
formSS.getRange("I6").clearContent();
formSS.getRange("J6").clearContent();
return row[RETURN_COL_IDX];
}
}
}
}
//====================================================================
function updateData() {
var SPREADSHEET_NAME = "Data";
var SEARCH_COL_IDX = 0;
var RETURN_COL_IDX = 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
var datasheet = ss.getSheetByName("Data"); //Data Sheet
var str = formSS.getRange("A6").getValue();
var values = ss.getSheetByName(SPREADSHEET_NAME).getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] == str) {
var INT_R = i+1
formSS.getRange("J6").setValue(new Date())
var values1 = [[formSS.getRange("A6").getValue(),
formSS.getRange("B6").getValue(),
formSS.getRange("C6").getValue(),
formSS.getRange("D6").getValue(),
formSS.getRange("E6").getValue(),
formSS.getRange("F6").getValue(),
formSS.getRange("G6").getValue(),
formSS.getRange("H6").getValue(),
formSS.getRange("I6").getValue(),
formSS.getRange("J6").getValue()]];
var values2 = [[formSS.getRange("A6").getValue(),
formSS.getRange("B6").getValue(),
formSS.getRange("C6").getValue(),
formSS.getRange("D6").getValue(),
formSS.getRange("E6").getValue(),
formSS.getRange("F6").getValue(),
formSS.getRange("G6").getValue(),
formSS.getRange("I6").getValue(),
formSS.getRange("J6").getValue()]];
values2[0].forEach(function(val) {
if (val === "") {
throw new Error("Please fill in Revisions, Project, Category, Subsystem, Description and Updated By Fields.");
}
})
datasheet.getRange(INT_R, 1, 1, 10).setValues(values1);
formSS.getRange("A6").clearContent();
formSS.getRange("B6").clearContent();
formSS.getRange("C6").clearContent();
formSS.getRange("D6").clearContent();
formSS.getRange("E6").clearContent();
formSS.getRange("F6").clearContent();
formSS.getRange("G6").clearContent();
formSS.getRange("H6").clearContent();
formSS.getRange("I6").clearContent();
formSS.getRange("J6").clearContent();
formSS.getRange("E4").clearContent();
SpreadsheetApp.getUi().alert(' Record Updated ');
return row[RETURN_COL_IDX];
}
}
}
There are several posts about this, I'll paste a response from one from yesterday. What I recommend specifically in your case is to run the script when there's an edit bye the user in a certain cell. For example a Tickbox, or a Drop-down menu (in a cell) that allows the user to select which function to run:
If you already have an onEdit function working, that's a simple trigger run by whoever is editing the sheet. Meaning that if you protect column A, it won't be editable by that simple trigger because the user won't have permissions
In order to work this out, I encourage you to protect your column as explained here, change your name function or extract in a new function the part about this specific code you're talking about; and set an installable trigger that runs on event. This way it'll be run as you used to but as it came from your own account. As you have permissions for editing ColA the timestamp will be set by the installable trigger but the other user won't be able to edit it since he/she doesn't have the permissions. Try it and let me know!

TIMEVALUE setting off a script

I'm trying to have TIMEVALUE set off a script. I have column P which is a Timer column that is subtracting a time from NOW to get a time value and then I am converting that to a TIMEVALUE in column O. When that value is either below or above certain values I want column N to then have a value so it would trigger my checkboxes script. But for some reason I can't get the TIMEVALUE to trigger. I tried to put it in another column and have the values CopyAndPasted Values Only into a column with that run on a time trigger of every minute, but apparently that doesn't count as an Edit or it's not reading the DisplayValue.
function onEdit(e) {
timeValue(e);
checkboxes(e);
rangerTime(e);
}
function rangerTime(e){
var editRow = e.range.getRow();
var editColumn = e.range.getColumn();
if (editColumn === 13 && e.value == "TRUE") {
const sh = e.range.getSheet();
sh.getRange(editRow, 25).setValue(sh.getRange(editRow, 25).getValue()+1);
sh.getRange(editRow, 13).setValue(" ")
}
}
function timeValue(e) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();
var editRow = e.range.getRow();
var editColumn = e.range.getColumn();
if(editRow > 3) {
var rowRange = sheet.getRange("O" + editRow);
var kCell = sheet.getRange("K" + editRow);
var kValue = kCell.getValue();
var nCell = sheet.getRange("N" + editRow);
var kHasValue = kValue != "";
if(editColumn > 10) {
if(rowRange.getDisplayValue()<0.02 && !kHasValue){
nCell.setValue(1);
}
if (rowRange.getDisplayValue()>0.5 && !kHasValue){
nCell.setValue(1);
}
if(kHasValue) {
nCell.setValue(" ");
}
}
}
}
function checkboxes(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ui = SpreadsheetApp.getUi();
var names = ss.getRange("N4:N");
var namesValues = names.getValues();
var checkboxes = ss.getRange("M4:M");
var cbRows = checkboxes.getHeight();
var cbValues = checkboxes.getValues();
var newCBValues = new Array(cbRows);
for (var row = 0; row < cbRows; row++) {
newCBValues[row] = new Array(0);
if (namesValues[row] == "" || namesValues[row] == " ") {
newCBValues[row][0] = " ";
}else{
if (cbValues[row][0] === true) {
newCBValues[row][0] = true;
}else{
newCBValues[row][0] = false;
}
}
}
checkboxes.setValues(newCBValues);
}
This part is run on the every minute Time Trigger:
function CopyandPaste() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('AA4').activate();
var currentCell = spreadsheet.getCurrentCell();
spreadsheet.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
currentCell.activateAsCurrentCell();
spreadsheet.getRange('O4').activate();
currentCell = spreadsheet.getCurrentCell();
spreadsheet.getSelection().getNextDataRange(SpreadsheetApp.Direction.DOWN).activate();
currentCell.activateAsCurrentCell();
spreadsheet.getRange('AA4:AA202').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
};
Column AA = TIMEVALUE(Column P)
From the question
I tried to put it in another column and have the values CopyAndPasted Values Only into a column with that run on a time trigger of every minute, but apparently that doesn't count as an Edit or it's not reading the DisplayValue.
You are right, only actions done by a user directly through the Google Sheets user interface will cause the edit trigger to be triggered.
One option is to make that your time-driven trigger besides changing the checkboxes also call the timeValue function but you have to refactor it or to mock the edit event object to pass it as the timeValue parameter.
Reference
https://developers.google.com/apps-script/guides/triggers

Checkboxes Triggering Addition Script in single row

In essence I'm trying to have a checkbox trigger addition. I have a number in Column A. When that number is entered checkboxes will appear in Column G. When that checkbox is checked I want it to trigger the addition function and add 1 to the same row in column A and not affect the other rows and then uncheck the checkbox.
So far, this is only working with Row 1 and not the other rows and I am not exactly sure why.
function onEdit (e) {
checkboxes(e);
addition(e)
}
function checkboxes(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ui = SpreadsheetApp.getUi();
var names = ss.getRange("A1:A");
var namesValues = names.getValues();
var checkboxes = ss.getRange("G1:G");
var cbRows = checkboxes.getHeight();
var cbValues = checkboxes.getValues();
var newCBValues = new Array(cbRows);
for (var row = 0; row < cbRows; row++) {
newCBValues[row] = new Array(0);
if (namesValues[row] == "" || namesValues[row] == " ") {
newCBValues[row][0] = " ";
}else{
if (cbValues[row][0] === true) {
newCBValues[row][0] = true;
}else{
newCBValues[row][0] = false;
}
}
}
checkboxes.setValues(newCBValues);
}
function addition(e) {
var ss = SpreadsheetApp.getActiveSheet();
var boxey = ss.getRange("G1:G")
var isAdd = boxey.getValue();
if (isAdd) {
Add();
boxey.setValue(false);
}
function Add() {
var ss = SpreadsheetApp.getActiveSheet();
var numbers = ss.getRange("A1:A");
numbers.setValue(numbers.getValue()+1);
}
Add one to column A of current row when checkbox in column G is checked
function onEdit(e) {
if (e.range.columnStart == 7 && e.value == "TRUE") {
const sh = e.range.getSheet();
sh.getRange(e.range.rowStart, 1).setValue(sh.getRange(e.range.rowStart, 1).getValue() + 1);
sh.getRange(e.range.rowStart, 7).setValue("FALSE")
}
checkboxes(e);//your current code
addition(e);//your current code
}

Sheets Run script on edit of a range of cells (False to True)

I have a script that needs to run when a sheet is edited. I need it to run anytime a box in column L (L2:L260) is checked. I originally wrote the script to run on a button push (check a number of boxes, click the button and it would run), but it can't be run by other people who need to be able to use it. The script originally worked great when it was click the button, but once I added in the onEdit stuff...it completely stopped working. Here's what I have:
function onEdit(e) {
//Get the sheet you want to work with.
var editrange = {
top : 2,
bottom : 260,
left : 11,
right : 11};
var thisrow = e.range.getrow();
if (thisrow < editrange.top || thisrow > editrange.bottom)
return;
var thiscolumn = e.range.getcolumn();
if (thiscolumn < editrange.left || thiscolumn > editrange.right)
return;
var ss = e.range.getSheet();
var sheet = ss.getSheetByName("Responsible");
//Grab the entire Range, and grab whatever values you need from it. EX: rangevalues
var range8 = sheet.getRange("K3:K90");
var range28 = sheet.getRange("M3:M90");
var range2values8 = range28.getValues();
var rangevalues8 = range8.getValues();
//Loops through range results
for (var i in rangevalues8) {
// for (var j in rangevalues) {
Logger.log("rangevalues8["+i+"]["+0+"] is:"+rangevalues8[i][0]);//Added
//Set the rules logic
if (rangevalues8[i][0] == true) { //Modified
//Set the cell
range2values8[i][0] += 1; //Directly add 1 to range2values
Logger.log(range2values8);//Added
}
}
//copy new information
var destination = ss.getSheetByName('Compiled Data');//whatever page
var destCell8 = destination.getRange("I183:I270");
destCell8.setValues(range2values8);
//clear checkboxes
var cleaning = ss.getSheetByName('Asset Bank');
var cleaningcell8 = cleaning.getRange("A3:A90").getValues();
range8.setValues(cleaningcell8);
}
Thanks for any help I can get!
After review of your code I guess the getcloumn() you've edited in an also erroneous method getcolumn(), the
var ss = e.range.getSheet();
var sheet = ss.getSheetByName("Responsible");
and the
e.range.getrow()
seems to be the major problems
correct syntax is:
getColumn();
getRow();
and you need to use the function getSheetByName(name) out from a spreadsheet object not a sheet object.
Here is the corrected code:
function onEdit(e) {
//Get the sheet you want to work with.
var editrange = {
top: 2,
bottom: 260,
left: 11,
right: 11
};
//getRow() and not getrow()
var thisrow = e.range.getRow();
if (thisrow < editrange.top || thisrow > editrange.bottom) return;
//getColumn() and not getcolumn()
var thiscolumn = e.range.getColumn();
if (thiscolumn < editrange.left || thiscolumn > editrange.right) return;
//Line that replaces the erroneous 'var ss = e.range.getSheet()';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Responsible");
//Grab the entire Range, and grab whatever values you need from it. EX: rangevalues
var range8 = sheet.getRange("K3:K90");
var range28 = sheet.getRange("M3:M90");
var range2values8 = range28.getValues();
var rangevalues8 = range8.getValues();
//Loops through range results
for (var i in rangevalues8) {
Logger.log("rangevalues8[" + i + "][" + 0 + "] is:" + rangevalues8[i][0]); //Added
//Set the rules logic
if (rangevalues8[i][0] == true) { //Modified
//Set the cell
range2values8[i][0] += 1; //Directly add 1 to range2values
Logger.log(range2values8); //Added
}
}
//copy new information
var destination = ss.getSheetByName('Compiled Data'); //whatever page
var destCell8 = destination.getRange("I183:I270");
destCell8.setValues(range2values8);
//clear checkboxes
var cleaning = ss.getSheetByName('Asset Bank');
var cleaningcell8 = cleaning.getRange("A3:A90").getValues();
range8.setValues(cleaningcell8);
}

Can't delete an event in my google calendar using scripts

I made a spreadsheet where I can easily manage my events in my google Calendar.
In the spreadsheet Row 1 has the dates, Row 2 has the specifics of the appointment and Row 3 saves the eventId of the event created by the script.
Every week starts on a new row.
The script works like it should and looks like this:
function CalenderUpdate() {
var calId = "xxxxxxxxxxxxxxxx#group.calendar.google.com";
var descr = "";
var date
var titel
var sheet = SpreadsheetApp.getActiveSheet();
var Afspraak = sheet.getRange(2,1,3,5).getValues();
var cal = CalendarApp.getCalendarById(calId);
for (j=2;j<9;j=j+3){
Afspraak = sheet.getRange(j,1,3,5).getValues();
for (i=0; i<5; i++){
descr ="";
date = Afspraak[0][i];
titel = Afspraak[1][i];
if (titel == "A"){ descr = "Late 14:00 - 21:00";}
if (titel == "M"){ descr = "Early 6:00 - 14:00";}
if (Afspraak[1][i] != ""){
var event = cal.createAllDayEvent(titel,date,{description:descr});
sheet.getRange(j+2,i+1).setValue(event.getId());
}
}
}
}
Now I want a new function. If I edit something in the schedule, I want it to update in my calendar. So I added a function onEdit that would delete the event if one created on that day, and if necessary create a new.
I started with this code to delete the event if something is edited. But it doesn't delete the appointment and I can't figure out why.
function onEdit(e){
var ss = SpreadsheetApp.getActiveSheet();
var range = e.range;
var rij = range.getRow();
var col = range.getColumn();
var afspraakId = ss.getRange(rij+1,col).getValue();
if (rij % 3 == 0) { ss.getRange(1,1).setValue(afspraakId); }
var calId = "xxxxxxxxxxxxxxx#group.calendar.google.com";
var cal = CalendarApp.getCalendarById(calId);
var event = cal.getEventSeriesById(id);
event.deleteEventSeries();
}
Hope someone can help me?
EDIT:
I changed the onEdit(e) to onEditInstallable(e) but the script never get triggered.
Even if I add a trigger by the menu
What do I do wrong?
EDIT2:
I've done some editing on my script. This is the end result:
function test_onEdit() {
onEditInstallable({
user : Session.getActiveUser().getEmail(),
source : SpreadsheetApp.getActiveSpreadsheet(),
range : SpreadsheetApp.getActiveSpreadsheet().getActiveCell(),
value : SpreadsheetApp.getActiveSpreadsheet().getActiveCell().getValue(),
authMode : "LIMITED"
});
}
function onEditInstallable(e){
var ss = SpreadsheetApp.getActiveSheet();
var range = e.range;
var rij = range.getRow();
var col = range.getColumn();
if (rij % 3 == 0 && col < 8) {
var cal = CalendarApp.getCalendarById("xxxxxxxxxxxxxxxxxx#group.calendar.google.com");
var event
var geg = ["","",""];
var descr ="";
for (i = 0 ; i < 3 ; i++){ geg[i] = ss.getRange(rij-1+i,col).getValue();}
if (geg[2] != ""){
event = cal.getEventSeriesById(geg[2]);
event.deleteEventSeries();
ss.getRange(rij+1,col).setValue("");
}
if (geg[1] != ""){
event = cal.createAllDayEvent(geg[1],geg[0],{description:descr});
ss.getRange(rij+1,col).setValue(event.getId());
}
}
}
The script works if I run the test_OnEdit. But the onEditInstallable doesn't trigger automatic? I'm an amateur in programming and I don't understand much of this page. Hope someone can help me figure this out.
Your second edit is a good approach, I'd suggest to add a couple of logs in the script to check the condition values.
I'd rather use the comments for this but it would definitely be too long and hard to read so I use the 'answer' format.
function onEditInstallable(e){
var ss = SpreadsheetApp.getActiveSheet();
var range = e.range;
var rij = range.getRow();
var col = range.getColumn();
Logger.log('rij = '+rij+' col = '+col);
if (rij % 3 == 0 && col < 8) {
var cal = CalendarApp.getCalendarById("xxxxxxxxxxxxxxxxxx#group.calendar.google.com");
var event
var geg = ["","",""];
var descr ="";
for (i = 0 ; i < 3 ; i++){ geg[i] = ss.getRange(rij-1+i,col).getValue();}
Logger.log('geg[2] = '+geg[2]);
if (geg[2] != ""){
event = cal.getEventSeriesById(geg[2]);
event.deleteEventSeries();
ss.getRange(rij+1,col).setValue("");
}
if (geg[1] != ""){
event = cal.createAllDayEvent(geg[1],geg[0],{description:descr});
ss.getRange(rij+1,col).setValue(event.getId());
}
}
}
I used this last piece of code and linked the test_onEdit script to a button in the spreadsheet. On the first time testing it from there Google gave a pop-up asking for extra authorizations. From then on everything works like a charm.
Now my spreadsheet automatically edits my agenda if I change something in the spreadsheet.
Thanks for the help everyone.
function test_onEdit() {
onEditInstallable({
user : Session.getActiveUser().getEmail(),
source : SpreadsheetApp.getActiveSpreadsheet(),
range : SpreadsheetApp.getActiveSpreadsheet().getActiveCell(),
value : SpreadsheetApp.getActiveSpreadsheet().getActiveCell().getValue(),
authMode : "LIMITED"
});
}
function onEditInstallable(e){
var ss = SpreadsheetApp.getActiveSheet();
var range = e.range;
var rij = range.getRow();
var col = range.getColumn();
Logger.log('rij = '+rij+' col = '+col);
if (rij % 3 == 0 && col < 8) {
var cal = CalendarApp.getCalendarById("xxxxxxxxxxxxxxxxxx#group.calendar.google.com");
var event
var geg = ["","",""];
var descr ="";
for (i = 0 ; i < 3 ; i++){ geg[i] = ss.getRange(rij-1+i,col).getValue();}
Logger.log('geg[2] = '+geg[2]);
if (geg[2] != ""){
event = cal.getEventSeriesById(geg[2]);
event.deleteEventSeries();
ss.getRange(rij+1,col).setValue("");
}
if (geg[1] != ""){
event = cal.createAllDayEvent(geg[1],geg[0],{description:descr});
ss.getRange(rij+1,col).setValue(event.getId());
}
}
}
Try this:
function deleteEvent(event) {
if (typeof event != 'undefined') {
Logger.log("Deleting event %s", event.getTitle())
event.deleteEvent()
}
}
function deleteEvents(eventCal,startTime,endTime,title){
// var oldEvents = eventCal.getEvents(startTime, endTime, {search: title});
var oldEvents = eventCal.getEvents(startTime, endTime);
Logger.log("oldEvents %s", oldEvents);
for (var j = 0; j < oldEvents.length; j++){
Logger.log("oldEvents[j] %s", oldEvents[j]);
deleteEvent(oldEvents[j]);
}
}