Create a timestamp in a specific cell in Google Sheets - google-apps-script

I'm trying to create a timestamp in a Google Sheet when a specific cell is edited. I need the timestamp to be added to cell B2 when cell A3 is edited. I also need the timestamp to be written as uppercase (in the format of 'FEBRUARY 20'). I have amended the date format in Google Sheets so it is displayed as month then year, but it also needs capitalising (Google Sheets is automatically formatting as 'February 20'). The code I have is
function onEdit(e) {
addTimestamp(e);
}
function addTimestamp(e){
//variables
var startRow = 3;
var targetColumn = 1;
var ws = "template";
//get modified row and column
var row = e.range.getRow();
var col = e.range.getColumn();
if(col === targetColumn && row >= startRow && e.source.getActiveSheet().getName() === ws){
var currentDate = new Date();
e.source.getActiveSheet().getRange(1,2).setValue(currentDate);
if(e.source.getActiveSheet().getRange(row,3),getValue() == ""){
e.source.getActiveSheet().getRange(row,3).setValue(currentDate);
} //END IF check if date created exists
} //END IF check column, row, worksheet
} //END function addTimestamp

Try this:
function onEdit(e) {
//e.source.toast('Entry');
var sh=e.range.getSheet();
if(sh.getName()!='************Your sheet name here*********')return;
if(e.range.columnStart==1 && e.range.rowStart==3) {
var M=['JANUARY','FEBRUARY','MARCH','APRIL','MAY','JUNE','JULY','AUGUST','SEPTEMBER','OCTOBER','NOVEMBER','DECEMBER'];
//e.source.toast('Flag1');
var ts= M[new Date().getMonth()] + " " + new Date().getDate();
//e.source.toast(ts);
sh.getRange(2,2).setValue(ts);
}
}

Related

Use range instead of array of indivdual cells

I have this code which works for cells A2-A4:
//The function onEdit ensures that checkboxes deleted (by mistake) in the sheet are immediately re-created.
function onEdit(e) {
var spreadsheet = SpreadsheetApp.getActive();
if(spreadsheet.getSheetName()=='MySheet') { //to avoid executing for another sheet
var checkboxCells = [
'A2','A3','A4'];
var range = e.range;
var value = range.getValue();
var a1Notation = range.getA1Notation();
if (checkboxCells.indexOf(a1Notation) != -1 && value != 'TRUE' && value != 'FALSE') {
range.insertCheckboxes();
}
}
};
However I need to work with a 1D range (since there are many cells) and hence I am trying to use this:
//The function onEdit ensures that checkboxes deleted (by mistake) in the sheet are immediately re-created.
function onEdit(e) {
var spreadsheet = SpreadsheetApp.getActive();
if(spreadsheet.getSheetName()=='MySheet') { //to avoid executing for another sheet
var checkboxCells = spreadsheet.getSheetByName('MySheet')
.getRange('MyRange').getA1Notation();
var range = e.range;
var value = range.getValue();
var a1Notation = range.getA1Notation();
if (checkboxCells.indexOf(a1Notation) != -1 && value != 'TRUE' && value != 'FALSE') {
range.insertCheckboxes();
}
}
};
I think this second version should work, but it does not.
Why does it not work?
Modification points:
In order to check whether the edited cell is included in the specific range you expect, the following sample script can be used. (var { range } = e;)
var checkboxCells = sheet.getRange('MyRange');
var startRow = checkboxCells.getRow();
var endRow = startRow + checkboxCells.getNumRows() - 1;
var startCol = checkboxCells.getColumn();
var endCol = startCol + checkboxCells.getNumColumns() - 1;
var check = range.rowStart >= startRow && range.rowEnd <= endRow && range.columnStart >= startCol && range.columnEnd <= endCol;
In order to check whether the edited cell is the checkbox, isChecked() can be used. In this case, when the cell is the checkbox, true or false are returned. When the cell is not the checkbox, null is returned. I thought that this might be able to be used.
When these points are reflected in your script, how about the following modification?
Modified script:
Please set your sheet name and your range.
function onEdit(e) {
var { range } = e;
var sheet = range.getSheet();
if (sheet.getSheetName() == 'MySheet') {
var checkboxCells = sheet.getRange('MyRange');
var startRow = checkboxCells.getRow();
var endRow = startRow + checkboxCells.getNumRows() - 1;
var startCol = checkboxCells.getColumn();
var endCol = startCol + checkboxCells.getNumColumns() - 1;
var check = range.rowStart >= startRow && range.rowEnd <= endRow && range.columnStart >= startCol && range.columnEnd <= endCol;
if (check && range.isChecked() === null) {
range.insertCheckboxes();
}
}
}
In this modified script, when a cell is edited, when the edited cell is included in MyRange, it checks whether the edited cell is a checkbox when the edited cell is not a checkbox, the checkboxes are inserted into the edited cell.
Reference:
isChecked()

Automatically sort Google Sheet by most recently updated row

I want to have a sheet which automatically sorts the most recently edited row to the top, in order to surface freshly edited results and not let them be buried by outdated entries.
Here's the solution I came up with for a Google Apps Script:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var dateColumn = 2; // What column should date be written to
var headerRows = 2;
var tableRange = "A3:M101"; // What data to sort.
var sheetName = 'Sheet name' // Name of the sheet to sort
if( sheet.getName() == sheetName ) { // Checks that we're on the correct sheet
var editedCell = sheet.getActiveCell();
var offset = dateColumn - editedCell.getColumn() // Finds the offset needed to move from edited cell to date column
if( editedCell.getColumn() != dateColumn && editedCell.getRow() > headerRows) { // Don't overwrite manually set dates or the header row(s)
var dateCell = editedCell.offset(0, offset); // Go to relevant date cell
var now = new Date();
now = Utilities.formatDate(now, "GMT", "yyyy/MM/dd HH:mm:ss"); // Format datetime
dateCell.setValue(now);
}
var range = sheet.getRange(tableRange);
range.sort( { column : dateColumn, ascending: false } ); // Sort range by date column, newest on top
// range.setWrapStrategy(SpreadsheetApp.WrapStrategy.WRAP); // Sets text wrapping to wrap if uncommented
}
}
Plus adding an event trigger on form submission.
This could work with an on form submit but not like you think
function onFormSubmit(e) {
const sh = e.range.getSheet();
if (sh.getName() == 'Sheet name' && e.range.columnStart != 2 && e.range.rowStart > 3) {
e.range.offset(0, 2 - e.range.columnStart).setValue(Utilities.formatDate(new Date(), "GMT", "yyyy/MM/dd HH:mm:ss"));
sh.getRange(3, 1, sh.getLastRow() - 2, 13).sort({ column: 2, ascending: false });
}
}
columStart will always be one so that will work
row start will work after you get past row 3
and the sheet will always have to be the linked sheet name and resorting the linked sheet seems kind of weird to me it's already sorted by time stamp

How to create timestamp on multiple columns in GSheet

Am havong some trouble creating a script to automate timestamp on GSheet. I have 2 columns - AD & AE, that I want it to have the date timestamp for when column L and AA are updated. Have tried the following script but doesn't seem to work.
function onEdit(e) {
addTimestamp(e);
}
function addTimestamp(e){
var startRow = 3;
var targetColumn = 12;
var targetColumn2 = 27;
var ws = "Brand List";
var row = e.range.getRow();
var col = e.range.getColumn();
if (col === targetColumn && row >= startRow && e.source.getActiveSheet().getName() === ws) {
var currentDate = new Date();
e.source.getActiveSheet().getRange(row,30).setValue(currentDate)
}
if (col === targetColumn2 && row >= startRow && e.source.getActiveSheet().getName() === ws) {
var currentDate = new Date();
e.source.getActiveSheet().getRange(row,31).setValue(currentDate)
}
}
Your script is working fine, but it seems that you're getting an error saying TypeError: Cannot read property 'range' of undefined.
This happens because the script is using a trigger to execute the function onEdit() whenever the spreadsheet is edited.
When executed, this trigger will pass an event object (e) as an argument to the function, which includes data such as the cell that was edited.
However, this event object is only passed if the sheet is edited, which doesn't happen if you run the function from the script editor.
So, to make it work, you need to edit the sheet as you'd do when using the script.
If you actually want to test it separately, you'd need to explicitly create this event object and pass it to the onEdit() function: How can I test a trigger function in GAS?
For those interested in the script used.
function onEdit(e) {
addTimestamp(e);
addTimestamp2(e);
}
function addTimestamp(e){
var startRow = 3;
var targetColumn = 12;
var targetColumn2 = 27;
var ws = "Brand List";
var row = e.range.getRow();
var col = e.range.getColumn();
if (col === targetColumn && row >= startRow && e.source.getActiveSheet().getName() === ws) {
var currentDate = new Date();
e.source.getActiveSheet().getRange(row,30).setValue(currentDate)
}
}
function addTimestamp2(e){
var startRow = 3;
var targetColumn = 12;
var targetColumn2 = 27;
var ws = "Brand List";
var row = e.range.getRow();
var col = e.range.getColumn();
if (col === targetColumn2 && row >= startRow && e.source.getActiveSheet().getName() === ws) {
var currentDate = new Date();
e.source.getActiveSheet().getRange(row,31).setValue(currentDate)
}
}

Insert Timestamp when copy/paste whole row and value inserts/edits in Column C in google sheets

I tried inserting timestamp when a row is being copied and data inserts or edits in Column C same row cell, but it works only on manual entry, not on copy-paste.
Please suggest to me what I am missing or doing wrong.
function onChange() {
var s = SpreadsheetApp.getActiveSheet();
var sName = s.getName();
var r = s.getActiveCell();
var row = r.getRow();
var ar = s.getActiveRange();
var arRows = ar.getNumRows()
// Logger.log("DEBUG: the active range = "+ar.getA1Notation()+", the number of rows = "+ar.getNumRows());
if( r.getColumn() == 3 && sName == 'Sheet1') { //which column to watch on which sheet
// loop through the number of rows
for (var i = 0;i<arRows;i++){
var rowstamp = row+i;
SpreadsheetApp.getActiveSheet().getRange('F' + rowstamp.toString()).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm"); //which column to put timestamp in
}
}
}//setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm:ss");
Use getLastColumn() to check whether column C is included in the pasted range.
Use getNumRows() to get the number of rows your copied range has, and so add the timestamp to all these rows.
No need to used an installed onChange() for this, a simple onEdit() is enough.
I'd also suggest to use event object in order to get information on which range was edited (even though this way you won't be able to fire this successfully from the script editor).
Edit: if you want to remove the timestamp when the range is cleared, you can just check that's the case, using every, or some, and clearContent if that's the case.
Code snippet:
function onEdit(e) {
var s = SpreadsheetApp.getActiveSheet();
var r = e.range;
var firstRow = r.getRow();
var numRows = r.getNumRows();
var firstCol = r.getColumn();
var lastCol = r.getLastColumn();
if((firstCol <= 3 || lastCol >= 3) && s.getName() == 'Sheet1') {
var emptyRange = r.getValues().every(row => row.every(value => value === ""));
var destRange = s.getRange(firstRow, 6, numRows);
if (emptyRange) destRange.clearContent();
else {
var dates = new Array(numRows).fill([new Date()]);
destRange.setValues(dates).setNumberFormat("MM/dd/yyyy hh:mm");
}
}
}
The following script will create timestamps starting from column F until the last column when you copy the row.
I think you are looking for this:
function onEdit(e) {
const startCol = 6; // column F
const s = e.source.getActiveSheet();
const sName = s.getName();
const ar = e.range;
const row = ar.getRow();
const arColumns = ar.getNumColumns();
const arRows = ar.getNumRows();;
if( sName == 'Sheet1') {
const rng = s.getRange(row,1,arRows,s.getMaxColumns());
check = rng.getValues().flat().every(v=>v=='');
if(check){
rng.clearContent();
}
else{
s.getRange(row,startCol,arRows,s.getMaxColumns()-startCol+1).setValue(new Date()).setNumberFormat("MM/dd/yyyy hh:mm");
}
}
}
Note:
Again, onEdit is a trigger function. You are not supposed to execute it manually and if you do so you will actually get errors (because of the use of the event object). All you have to do is to save this code snippet to the script editor and then it will be triggered automatically upon edits.

Google Sheet: Insert timestamp in specific rows while edit specific range

Because I'm low of scripting but I really have to use it (I didn't found any other solution) I would like to ask you for a help with timestamp.
I'm looking for help with function onEdit that would allow me to add timestamp in specific column (S) in each of row while editing specific ranges F4:Q4, F5:Q5. The most important thing there is that I would like to avoid few rows (because it's a title rows and I don't want to add timestamp while changing title rows)
Part of it is working with code below, But there's not included mechanism of editing only specific range (any change in whole row is noticed as a modification) and also there is nothing for skipping the title rows
function onEdit(e) {
// Your sheet params
var sheetName = "Sklad";
var dateModifiedColumnIndex = 4;
var dateModifiedColumnLetter = 'S';
var range = e.range; // range just edited
var sheet = range.getSheet();
if (sheet.getName() !== sheetName) {
return;
}
// If the column isn't our modified date column
if (range.getColumn() != dateModifiedColumnIndex) {
var row = range.getRow();
var time = new Date();
time = Utilities.formatDate(time, "GMT-08:00", "dd/MM/yy, hh:mm:ss");
var dateModifiedRange = sheet.getRange(dateModifiedColumnLetter + row.toString());
dateModifiedRange.setValue(time);
};
};
I would be very grateful for your help,
Regards
You can add the number of header rows as part of your second if()
This change will not add a timestamp in the first 4 rows if edited.
if (range.getColumn() != dateModifiedColumnIndex && range.getRow() > 4) {
Thank you #James
It works for me as
function onEdit(e) {
// Your sheet params
var sheetName = "Sklad";
var dateModifiedColumnIndex = 3;
var dateModifiedColumnLetter = 'S';
var range = e.range; // range just edited
var sheet = range.getSheet();
if (sheet.getName() !== sheetName) {
return;
}
// If the column isn't our modified date column
if (range.getColumn() != dateModifiedColumnIndex && range.getRow() > 3 && range.getRow() != 8 && range.getRow() != 15 && range.getRow() != 32 && range.getRow() < 49) {
var row = range.getRow();
var time = new Date();
time = Utilities.formatDate(time, "GMT", "dd-MM-yyyy");
var dateModifiedRange = sheet.getRange(dateModifiedColumnLetter + row.toString());
dateModifiedRange.setValue(time);
};
};