I have a Google Sheet file that has many tabs (sheets) in it. What I am looking to do is place a timestamp when any cell on a specific page is updated or modified.
Sheet name = "Data-Dashboard"
Cell to place timestamp on "Data-Dashboard" is B1.
I wonder if having the timestamp on the sheet that is updating the timestamp on edit if it will create a loop so then I can exclude row 1 and just monitor the remaining rows and columns.
Here is my starting point:
function onEdit(e) {
var col = e.range.getColumn();
if(col == 1, 2, 3, 4, 5, 6) {
e.source.getActiveSheet().getRange(1,2).setValue(new Date())
That puts the timestamp in the correct place and works when I modify anything in rows A-F. But it applies to all sheets, I need to limit it to a single sheet. Any help would be appreciated!
From the question
What I am looking to do is place a timestamp when any cell on a specific page is updated or modified.
Sheet name = "Data-Dashboard"
Cell to place timestamp on "Data-Dashboard" is B1.
The onEdit trigger is triggered when any edit is done through the Google Sheets UI, to limit the writing of the timestamp to only do it when the certain sheet is edited, then you should add a conditional statement, i.e. an if statement.
function onEdit(e){
/* Using a conditional operator to assign the active sheet
when this function is ran without providing an event object, i.e.
when running from the script editor */
const sheet = e ? e.range.getSheet() : SpreadsheetApp.getActiveSheet();
if(sheet.getName() === 'Data-Dashboard'){
sheet.getRange('B1').setValue(new Date();
}
}
Regarding your starting point and that it's working when columns A-F are edited, it's worthy to note while all the parts are evaluated, only the last part is considered as the condition of the if statement, in this case 6, which is a truthy value, meaning that always will be true. The following version includes the condition to log the timestamp only when columns A to F from Data-Dashboard sheets are edited.
function onEdit(e){
/* Using a conditional operator to assign the active sheet
when this function is ran without providing an event object, i.e.
when running from the script editor */
const sheet = e ? e.range.getSheet() : SpreadsheetApp.getActiveSheet();
if(sheet.getName() === 'Data-Dashboard' && e.range.columnStart <= 6){
sheet.getRange('B1').setValue(new Date();
}
}
References
comma operator
Related
How do I restrict a trigger to a specific sheet/tab?
Try this:
function onEdit(e) {
const sh = e.range.getSheet();
var col = e.range.getColumn();
if (sh.getName() == "Your Sheet Name" && e.range.columnStart < 7 && e.range.rowStart > 1) {
sh.getRange(1, 2).setValue(new Date());
}
}
Related
I have a public spreadsheet, where people can enter their names under the column "Name". Everything in this sheet is protected, except for the cells in the column "Name". Since the spreadsheet is public, I want to avoid a situation where someone can troll and delete all the names that have been inputted. Hence, I'm trying to set up a script using the on edit triggers to protect the cell in this range after anyone has entered their name in a cell. So far I've been manually protecting the cells after a name has been entered.
I've found out that the best way to do this would be to use the on edit trigger. I have used javascript before but as I'm new to google spreadsheet scrips, I can't get my script to run like it's supposed to. The current script is supposed to automatically protect the range on edit, and add a description of when the protection was done.
Sample spreadsheet with the script in it here: https://docs.google.com/spreadsheets/d/18NlVKcaeyOkgqIa6WAuDsu5TSYK37m_vXLmp7p7Q8kc/edit?usp=sharing
function protectOnEdit(event) {
var ss = SpreadsheetApp.getActive();
var range = ss.getRange('Sheet1!A2:A1000');
var timeZone = Session.getScriptTimeZone();
var stringDate = Utilities.formatDate(new Date(), timeZone, 'dd/MM/yy HH:mm');
var description = 'Protected on ' + stringDate;
var protection = range.protect().setDescription(description);
// below code taken directly from Google's documentation
var me = Session.getEffectiveUser();
protection.addEditor(me);
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) {
protection.setDomainEdit(false);
}
}
Reference: https://developers.google.com/apps-script/reference/spreadsheet/range#protect()
The data range in question is A2:A1000 and currently it -seems- to partially work, however, it protects the WHOLE range after editing a single cell, instead of just protecting the edited cell like it's supposed to.
Are there any steps I'm missing in order for the script to lock the cells individually, instead of the whole range? Any insights are very appreciated!
I have made some corrections:
function protectOnEdit(e) {
var range = e.range;
// Be sure to have edited the sheet "Sheet1"
if (range.getSheet().getName() != "Sheet1") return;
// Be sure to have a single cell as edited range
if (range.getWidth() != 1 || range.getHeight() != 1) return;
// Be sure to have edited cell inside A2:A1000
if (range.getColumn() != 1 || range.getRow() < 2) return;
// Be sure to have non-blank new value
if (!e.value) return;
// Protect this range
var timeZone = Session.getScriptTimeZone();
var stringDate = Utilities.formatDate(new Date(), timeZone, 'dd/MM/yy HH:mm');
var description = 'Protected on ' + stringDate;
var protection = range.protect().setDescription(description);
protection.removeEditors(protection.getEditors());
if (protection.canDomainEdit()) protection.setDomainEdit(false);
}
At first the script checks several conditions for desired protection. They seem to me to be important for the task. If all of them are TRUE, then protects a single cell. The spreadsheet owner has no restrictions to edit protected cells but other editors have.
Of course, the owner should install a trigger for this function properly to automate the process.
I need to create an operation on another sheet of where the event came from.
For example, when any cell in the "data" sheet is edited/changed, dump a timestamp in the "other" sheet (within the same spreadsheet). If it helps to make the code faster, the "data" sheet will at least always have cell 1,1 edited even if it's the same value because something else automatically dumps data and re-writes the entire "data" sheet.
The main problem is that I don't know what value to compare the conditional statement with since I don't know what values will change in the see. See below.
// Dumps the timestamp of the last time the "Data" sheet was edited
function onEdit(e){
var dataSheetLastColumn = thisSpreadsheet.getSheetByName("Data").getLastColumn();
var dataSheetLastRow = thisSpreadsheet.getSheetByName("Data").getLastRow();
var dataSheetEvent = e.source.getSheetByName("Data").getRange(1, 1, dataSheetLastRow, dataSheetLastColumn);
// puts a time-stamp on another sheet
var theOtherSheet = thisSpreadsheet.getSheetByName("Other");
theOtherSheet.getRange(2, 1).setValue(new Date());
}
try this:
function onEdit(e) {
if(e.range.getSheet().getName()=='Other'){return;}
e.source.getSheetByName('Other').getRange(2,1).setValue(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy HH:mm:ss"));
}
Note: this event only occurs on user edits.
Simple Trigger Restrictions
function onEdit(e) {
if(e.range.getSheet().getName()!='Data' ) {return;}
e.source.getSheetByName('Other').getRange(2,1).setValue(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy HH:mm:ss"));
}
I'm continually adding new rows to Google Sheets with numerical values in Column C. I need a script (not a formula!) to do 2 things with those numbers.
Change the number format to remove commas from any numbers
Add 200 to each number
I've got the script for part 1...
function setFormat(){SpreadsheetApp.getActiveSheet().getRange("C2:C").setNumberFormat('##########0');}
But I need help with part 2.
Both scripts need to occur immediately upon creation of the number in Column C.
I can't use formulas for these changes. I need to use scripts.
Thank you!
You can write whole code within onEdit() function
like this:
function onEdit(e){
var range = e.range;
if(range.getColumn() == 3){ //Column C is 3rd column
SpreadsheetApp.getActiveSheet().getRange("C2:C").setNumberFormat('##########0');
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var r = e.source.getActiveRange();
var cell = r.getA1Notation();
var tempval = sheet.getRange(cell).getValue();
var numval = parseFloat(tempval)+200;
sheet.getRange(cell).setValue(numval);
}
}
Hope this will help you.
Thanks.
My script is supposed to move a row from one google spreadsheet to another based on a value in a cell. It fails to do so, and I think it's because of the onEdit() function but can't figure it out. I found a solution for different sheets in the same spreadsheet but not in different spreadsheets. My code is below.
function onEdit(e) {
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ss = e.source.getActiveSheet();
var r = e.source.getActiveRange();
if(s.getName() == "source_sheet" && r.getColumn() == 7 && r.getValue() == "Pavlovo"){
//Get full range of data
var SRange = ss.getRange(1, 3, 1, 5);
//get A1 notation identifying the range
var A1Range = SRange.getA1Notation();
//get the data values in range
var SData = SRange.getValues();
// tss = target spreadsheet
var tss = SpreadsheetApp.openById('1_t7BDCWgHJDip_cndzVashxLDQ_pVS6obi3I9TB_EJI');
var ts = tss.getSheetByName('Vitosha'); // ts = target sheet
//set the target range to the values of the source data
ts.getRange(A1Range).setValues(SData);
}
}
You are using a simple trigger onEdit. Such triggers run without authorization and therefore are subject to several restrictions, such as:
They can modify the file they are bound to, but cannot access other files because that would require authorization.
This is why SpreadsheetApp.openById fails to execute in your code.
Solution: rename the function to something other than onEdit, and add an installable trigger running on edits. An installable trigger runs as you (i.e., the user who created it), and therefore can access any files that you can access.
I've been working on this script in Google Apps Script for a little while now and think I've got it almost figured out. I could really use another pair of eyes though, as it hasn't yet worked to completion.
What I'm trying to do:
I'm working on a sheet dealing with tentative and actual dates. These two dates are in adjacent columns. Once the "actual" date gets filled into its cell, I would like the "tentative" date to be deleted.
Here is my script thus far:
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange('F4:F');
var range2 = sheet.getRange('E4:E');
var rule = range.getDataValidation();
if (rule != null) {
var criteria = rule.getCriteriaType();
var args = rule.getCriteriaValues();
var clear = range2.clear({validationsOnly: false});
}
}
What do I need to do to get this script running?
It appears you want to delete the value in column E if column F was filled. If so, I don't see the need for dealing with data validation rules. The following script checks that the edited cell is in column F, row >= 4, and that the new value in the cell is a date. If these conditions hold, it clears the cell to the left (using offset).
function onEdit(e) {
if (e.range.getColumn() == 6 && e.range.getRow() >= 4) {
if (e.range.getValue() instanceof Date) {
e.range.offset(0, -1).clear();
}
}
}
Note: this script uses the event object passed to onEdit function. Interestingly, its "value" property turned out to be not useful here, because it is not a date object even when a user enters a date. This is what I use e.range.getValue() instead.