I have been messing around to build a google worksheet with script. So basically, in this file whenever there is input on column 1 and 4, there will be a timestamp shown in the next cell. And when the input is removed, the timestamp is clear. Everything runs fine so far, however as some weird issue happen. If instead of input in column 1 & 4, I paste values to the range, no timestamp appear or if I paste with the timestamp, the pasted timestamp will disappear. I don't know what happened or if you are clear on what I'm trying to ask. Anyway, here the script I'm using:
function onEdit(e) {
var s = SpreadsheetApp.getActiveSheet();
var r = e.range;
var nextCell = r.offset(0, 1);
if( s.getName() == "Nhap" && (r.getColumn() == 1 || r.getColumn() == 3) ){
if( nextCell.getValue() === '' && e.value !=null)
{
var time = Utilities.formatDate(new Date(), "GMT+7", "MM/dd/yyyy HH:mm:ss");
nextCell.setValue(time);
}
else{ nextCell.clearContent()}
};
}
Thanks
e.value undefined when copy/pasting range:
When a range is copied, instead of manually inputting a value on a cell, the value parameter from the corresponding event object (e.value) is undefined. This is a known behaviour and it has been reported several times in Issue Tracker before:
Installable onEdit function doesn't pass correct event.value when pasting cells into spreadsheet.
Apps Script On Edit New Value is undefined when value is pasted in cell
for onEdit trigger value is null if there was copy-paste of cell
While this is still under investigation, this doesn't seem to be intended behaviour. While the description for the value parameter says it will only be populated when the edited range is a single cell,
value: New cell value after the edit. Only available if the edited range is a single cell.
This behaviour also happens when the copied/pasted range is a single cell. See this related answer from Diego.
Issue:
Since e.value is undefined when pasting the range, the following condition is never true:
if( nextCell.getValue() === '' && e.value !=null)
So the code goes to:
else{ nextCell.clearContent()}
That is, the timestamp cell is cleared of content.
Solution:
You can avoid this by changing e.value to r.getValue() (see Range.getValue()), which will be populated even when the range is copy/pasted:
if( nextCell.getValue() === '' && r.getValue() !=null)
Another issue:
Also, in your current code, when the timestamp cell is not empty, this condition is always false, so the timestamp cell is cleared:
if( nextCell.getValue() === '' && e.value !=null)
This is disregarding whether the range is pasted or the cell is inputted manually. If you don't want this to happen, remove nextCell.getValue() === '' from your condition.
Edit:
If you want to remove timestamp when cell is emptied, check that cell value is not an empty string ("" !== null):
if (r.getValue() !="")
Related
Based purely on the execution log it appears this script is running EVERY time anyone edits the sheet, but I only need it to run when column 3 or column 7 are edited. What do I add into the script to tell it to do this? I'm not super script literate so any help is greatly appreciated!!
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "FORD" ) {
var r = s.getActiveCell();
if( r.getColumn() == 3) {
var nextCell = r.offset(0,19);
if( nextCell.getValue() === '' )
nextCell.setValue(new Date()).setNumberFormat('MM/dd/yyyy HH:mm:ss');
}
if( r.getColumn() == 7) {
var nextCell = r.offset(0,16);
if( nextCell.getValue() === '' )
nextCell.setValue(new Date()).setNumberFormat('MM/dd/yyyy HH:mm:ss');
}
}
}
Is it weird that your code actually works on mine? If I understood your issue correctly, you want your script to be ran when columns 3 and 7. I don't see any issues on your script but I think this approach below should be better. We will use the e object to get your data.
Code:
function onEdit(e) {
var s = e.source.getActiveSheet();
if( s.getName() == "FORD" ) {
var r = e.range;
if( r.getColumn() == 3) {
var nextCell = r.offset(0,19);
if( nextCell.getValue() === '' )
nextCell.setValue(new Date()).setNumberFormat('MM/dd/yyyy HH:mm:ss');
}
if( r.getColumn() == 7) {
var nextCell = r.offset(0,16);
if( nextCell.getValue() === '' )
nextCell.setValue(new Date()).setNumberFormat('MM/dd/yyyy HH:mm:ss');
}
}
}
Practically the same logic your script does, but now, we do not get the data directly onto the sheet but the onEdit event object.
If you meant like the onEdit function should only be TRIGGERED during edits on column 3 and 7, that won't do.
onEdit function is triggered every time the sheet is edited manually, whatever range it is. We can only restrict the function on doing things by adding conditions but we can't practically stop triggering the function when a manual edit has been done.
It will always run on every manual edit, it is just a matter of restriction where we limit the function to do things based on what conditions we added. (Conditions such as running certain commands only if the sheet name is FORD and columns 3 or 7 are edited)
If I misunderstood your question, I sincerely apologize.
Edit:
I'm looking for other sources and it seems you can use switch-case instead of classic if-else statement as it is faster than the latter in large data. I've tested it and it seems it does have some significant difference in single tests. It will be significantly more faster in large data.
if-else:
switch-case:
Test:
The tests were the same on both if-else and switch-case.
First 3 tests are edits on column 3, second 3 tests were on column 7 and last 3 were non-3/7 edits
Run times are read bottom-up
This actually varies per test but pasted these results as it seems to be close to the average.
There are quotas that are in place and should be checked. See link for more details. You might need a paid subscription if you want more.
I want to add the current data and time in a specific column with any edit in whole sheet. I tried to write a script and got a little bit success but could not get desired result.
When I run the below script then it insert the time stamp in the very next column but I want to insert the timestamp in a specific column e.g in Column D.
Secondly it only works when I change values in a cell, but I want to add time stamp also when I change even color of a cell too.
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Sheet1" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() ) { //checks the column
var nextCell = r.offset (0,1) ;
// if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date() );
}
}
}
Kindly help me to get the desired result.
if you want to insert the timestamp in a specific column e.g in Column D:
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "Sheet1" ) { //checks that we're on the correct sheet
var r = s.getActiveCell();
if( r.getColumn() ) { //checks the column
var nextCell = s.getRange('D' + r.getRow()); // change D to any column needed
// if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date() );
}
}
}
Notes:
onEdit(e) runs when a user changes a value in a spreadsheet.
tests show onEdit runs when cells borders are changed
onEdit does NOT run when color is changed, font is changed.
I have a code that puts a timestamp in when column 1 is edited and then a second timestamp when another column has the word 'collected' input to it. From this I then work out time it took to be collected and use that data. However if someone edits column 1 again it updates the timestamp so I'm looking for a script to allow it to only do it on first edit. Here is my current script;
function onEdit(e) {
var sheet = SpreadsheetApp.getActiveSheet();
if( sheet.getName() == "CC sheet" ) {
//Update timestamp when changed to collected
var range = sheet.getActiveCell();
Logger.log(range.getColumn())
if( range.getColumn() == 7.0 ) { //if we are in the status column...
var nextCell = range.offset(0, 2);
if(range.getValue() == 'Collected')
if( nextCell.getValue() === '' ) //is empty?
nextCell.setValue(new Date());
}
//end
}
if(e.source.getActiveSheet().getName() !== 'CC sheet' || e.range.columnStart !== 1) return;
e.range.offset(0, 5).setValue(e.value ? new Date() : null);
}
It is the bottom bit I need to change to only update on first edit. Any help with this would be much appreciated.
replace last row or code with this one:
if (e.range.offset(0, 5).getValue() === '') {
e.range.offset(0, 5).setValue(e.value ? new Date() : null);
}
it's the same 'is empty?' check, as you have in the first part of script.
I am making a sign-up sheet with available dates on the top, and names on the side. When a person puts their initials in one of the date columns, I'd like the date on top to change to StrikeThrough so that it is easily identified to others as being no longer available for selection. Any ideas on how to do this? So it needs to be something like: If ANY text appears anywhere in column E, Then E1:E3 changes to StrikeThrough.... Thanks!
I am using Google Sheets, PC, Windows 8. I am new here and if won't let me post images... Here is an idea of what I'm working with: https://dl.dropboxusercontent.com/u/41966437/OVERTIME%20SIGN%20UP%20%20%20Google%20Sheets.png
See my answers to the question below for more details. Thanks!
Can you see if this works ? As a bonus I also made the line-though dissappear if the intitials are erased (and no other initials are in the same column).
function onEdit(e) {
var ss = e.source.getActiveSheet();
if (e.range.columnStart < 5 || e.range.rowStart < 3) return;
e.range.offset(-e.range.rowStart + 1, 0)
.setFontLine(e.value ? "line-through" : "normal");
}
Note: the script will work on every sheet of the spreadsheet(workbook) if you need it to work on 1 sheet only, fill in the sheet name in the code below and use this instead of the previous:
function onEdit(e) {
var ss = e.source.getActiveSheet();
if (ss.getName() !== 'Sheet1' || e.range.columnStart < 5 || e.range.rowStart < 3) return;
e.range.offset(-e.range.rowStart + 1, 0)
.setFontLine(e.value ? "line-through" : "normal");
}
I am using Google Spreadsheets and what I am trying to do is update the cells that contain a timestamp in the Time last Updated column each time I update a cell in the same row.
Is there any way I can achieve that?
Thanks in advance,
not tested but something like this should work. Since you didn't provide any details, you will have to change some variables according to your needs.
function onEdit(e) {
var startCol = 2,
endCol = 10,
tsCol = 11, //this is the column where the timestamp will appear
startRow = 2,
sheetName = 'Sheet1', //this is the name of the sheet you want the script to work on.
curSheet = e.source.getActiveSheet();
//exit script when edits are made another sheet, or in the first row, or before col 2 or after col 10
if (curSheet.getName() !== sheetName || e.range.columnStart < startCol || e.range.columStart > endCol || e.range.rowStart < startRow) return;
curSheet.getRange(e.range.rowStart, tsCol)
.setValue(new Date());
}