I am adding timestamp in col a if colb is edited on 3 sheets.
I have the trigger working onEdit and the information will be updated automatically. It works fine for one, but for 3 im getting an error and cannot run the script.
Is there a simpler way to look for edit in column b in three sheets than what I am doing?
function onEdit() {
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() == "Igualdad Op Hom Mu") {
var r = s.getActiveCell();
if (r.getColumn() == 2) {
var nextCell = r.offset(0, -1);
if (nextCell.getValue() === '')
nextCell.setValue(new Date());
var s2 = SpreadsheetApp.getActiveSheet();
if (s2.getName() == "Incl Per Disc") {
var r2 = s2.getActiveCell();
if (r2.getColumn() == 2) {
var nextCell2 = r2.offset(0, -1);
if (nextCell2.getValue() === '')
nextCell2.setValue(new Date());
var s3 = SpreadsheetApp.getActiveSheet();
if (s3.getName() == "Empr y Col") {
var r3 = s3.getActiveCell();
if (r3.getColumn() == 2) {
var nextCell3 = r3.offset(0, -1);
if (nextCell3.getValue() === '')
nextCell3.setValue(new Date());
}
}
}
}
}
}
}
Try this:
function onEdit(e) {
const sh=e.range.getSheet();
const shts=['Igualdad Op Hom Mu','Incl Per Disc','Empr y Col']
if( shts.indexOf(sh.getName())!=-1 && e.range.columnStart==2) {
const ts=Utilities.formatDate(new Date,Session.getScriptTimeZone(),"yyyy/MM/dd HH:mm:ss");//time stamp
const rg=e.range.offset(0,-1);//next cell to the left
if(rg.getValue()=='') {
rg.setValue(ts);
}
}
}
This function requires the onedit trigger event object so you cannot run this script from the script editor unless you supply the event object.
Related
I am trying to run a Google App script that unhides columns, and then rehides columns based whether the cell reference says Blank or not. This is determined by a drop down in a single cell. I got the script to run fine (if a little clunky) whenever any edit is made, but when I try to add the specification of cell it flags an error with the range.
I'm very new to this so I'm a bit out of my depth so any help is appreciated!
function onEdit(e) {
if (e.range.getA1Notation() === 'B2') {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActive().getSheetByName("Group M0 loot");
sheet.showColumns(9, 35);
var range = sheet.getRange("4:4");
var num_cols = range.getNumColumns();
for (var i = 9; i <= num_cols; i++) {
var value = sheet.getRange(4,i).getValue();
if (value == "Blank") {
sheet.hideColumns(i);
};
}
}
}
Try this:
function onEdit(e) {
const sh = e.range.getSheet();
if (sh.getName() == "Group M0 loot" && e.range.columnStart == 2 && e.range.rowStart == 2) {
sh.showColumns(9, 35);
sh.getRange(4,1,1,sh.getLastColumn()).getValues().flat().forEach((c,i) => {
if(!c) {
sh.hideColumns(i + 1);
}
});
}
}
I'm trying to make a script that when info is pasted into Cell 'J3' it will make a time stamp in cell 'AA1' and additionally it will also make a time stamp in column 'AI' in the first cell that doesn't already have a time stamp.
This would be so the sheet makes a time stamp that gets overridden each time that info is pasted into the sheet, but also make a static time stamp separately of each time info is pasted into the sheet.
I have a script that makes the timestamp that only updates when info is pasted into 'J3'
function:
onEdit(e) {
const sh = e.range.getSheet();
if (e.range.columnStart == 10 && e.range.rowStart == 3 && !e.value) {
sh.getRange("AA1").setValue(new Date());
}
}
I also have a script that takes info from one tab and copies it over to another tab on the first available row.
function Delete() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Testing'), true);
jumpToFirstEmptyBasic()
spreadsheet.getRange('Live Data!S2:AE1001').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Live Data'), true);
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A2:M1001').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getRange('Live Data!A2')
};
function jumpToFirstEmptyBasic() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Testing"); // << Change the sheet name to your own sheet.
var lastRow = sheet.getLastRow();
Logger.log(lastRow);
sheet.getRange(lastRow+1,1).activate();
};
Over all, I'm trying to add some of the seconds code to the first so that it has a second function of making a list of time stamps on the same tab whenever info is pasted into the 'J3' cell.
So far this is what I have put together, but it doesn't work, and I'm not experienced enough with python to find out why:
function onEdit(e) {
const sh = e.range.getSheet();
if (e.range.columnStart == 10 && e.range.rowStart == 3 && !e.value) {
sh.getRange("AA1").setValue(new Date());
jumpToFirstEmptyBasic()
sh.getRange(lastRow).setValue(new Date());
}
function jumpToFirstEmptyBasic() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var lastRow = ss.getLastRow();
Logger.log(lastRow);
ss.getRange(lastRow+1,1).activate();
};
}
Try this:
function onEdit(e) {
e.source.toast("Entry");
const sh = e.range.getSheet();
if (e.range.columnStart == 10 && e.range.rowStart == 3) {
e.source.toast("Gate1");
let lr = Number(getColumnHeight(27, sh, e.source));
sh.getRange(Number(lr) + 1, 27).setValue(new Date());
sh.getRange("AA1").setValue(new Date();)
e.source.toast(`The are ${Number(lr) + 1} timestamps on this page.`);
}
}
function getColumnHeight(col, sh, ss) {
var ss = ss || SpreadsheetApp.getActive();
var sh = sh || ss.getActiveSheet();
var col = col || sh.getActiveCell().getColumn();
var rcA = [];
if (sh.getLastRow()){ rcA = sh.getRange(1, col, sh.getLastRow(), 1).getValues().flat().reverse(); }
let s = 0;
for (let i = 0; i < rcA.length; i++) {
if (rcA[i].toString().length == 0) {
s++;
} else {
break;
}
}
return rcA.length - s;
//const h = Utilities.formatString('col: %s len: %s', col, rcA.length - s);
//Logger.log(h);
//SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(h).setWidth(150).setHeight(100), 'Col Length')
}
This may also work for you. But I find it unreliable at times and I'm not sure why.
function onEdit(e) {
e.source.toast("Entry");
const sh = e.range.getSheet();
if (e.range.columnStart == 10 && e.range.rowStart == 3) {
e.source.toast("Gate1");
let lr = Number(sh.getRange("AA1").getDataRegion(SpreadsheetApp.Dimension.ROWS).getHeight());
sh.getRange(Number(lr) + 1, 27).setValue(new Date());
sh.getRange("AA1").setValue(new Date());
e.source.toast(`The are ${Number(lr) + 1} timestamps on this page.`);
}
}
But if it works for you it will relieve you of using the helper function getColumnHeight();
I'm new at this so thank you for your help and your patience.
Example: I have a shared spreadsheet with a protected range 'Y:Y' where colleagues update line items. One line item we want to flag when they change it is in column 'X:X'.
My desire is to set up a trigger that runs every 24 hours and it copies the values in column 'X:X' and pastes them into empty or blank values in column 'Y:Y'.
Then a simple DAX formula would compare X to Y. This would simplify a script I'm currently using that runs every time there's an edit.
function OnEdit() {
var s = SpreadsheetApp.getActiveSheet();
if( s.getName() == "PTL" ) { //checks that we're on PTL or not
if( s.getActiveCell().getColumn() == 7 ) { //checks that the cell being edited is in column G
var modify = s.getActiveCell().offset(0, 7);
modify.setValue(new Date());
var baseline = s.getActiveCell().offset(0, 6);
if( baseline.getValue() === '' ) //checks if the adjacent cell is empty or not?
baseline.setValue(new Date());
}
}
}
Try it this way:
function OnEdit(e) {
var sh = e.range.getSheet();
if (sh.getName() == "PTL" && e.range.columnStart == 7) {
e.range.offset(0,7).setValue(new Date());
if (e.range.offset(0, 6).getValue() == '')
e.range.offset(0,6).setValue(new Date());
}
}
function notsurewhatyouwant() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('PTL');
const xy = sh.getRange(1, 24, sh.getLastRow(), 2).getValues();
xy.forEach((r, i) => {
if (r[1] == null) {
sh.getRange(i+1,25).setValue(r[0]);
}
});
}
function createTrigger() {
if(ScriptApp.getProjectTriggers().filter(t => t.getHandlerFunction() == "notsurewhatyouwant").length == 0) {
ScriptApp.newTrigger('notsurewhatyouwant').timeBased().everyDays(1).atHour(0).create();
}
}
I want to copy the data from G11:G22 to the last column of the sheet starting from row 11 by using onEdit function. So, the script will be triggered once I select Transfer in cell F7. After running the script, the data should appear in range H11:H22 since column H is the last column in the sheet. How should I achieved that? This is what I have tried:
function onEdit(e){
var ss = SpreadsheetApp.getActiveSheet();
var lastrow = ss.getLastRow()
for( var k = 2; k <= lastrow ; k++) {
var m = 1;
while( sheet.getRange(k,m).isBlank() == false) {
m = m +1;
}
var lastcolumn = m
}
var destRange = ss.getRange(11,lastcolumn+1)
if (e.range.columnStart == 6 && e.range.rowStart == 7){
if (e.value == 'Transfer'){
var source = ss.getRange("G11:G22")
source.copyTo (destRange, {contentsOnly: true})
e.range.clearContent()
}
}
}
I think the problem comes from the For loop but I have no idea what is wrong. Hope to get some helps on this, thank you.
Based on your screenshot I suppose you can use getLastColumn()
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSheet();
var destRange = ss.getRange(11, ss.getLastColumn() + 1)
if (e.range.columnStart == 6 && e.range.rowStart == 7) {
if (e.value == 'Transfer') {
var source = ss.getRange("G11:G22")
source.copyTo(destRange, { contentsOnly: true })
e.range.clearContent()
}
}
}
No need for loop to get the last column if there is no more filled cels on the right side of the sheet.
I have these scripts working separately but when I combine them or create two different scripts only one will function. If found that the conditional formatting tool was bogging down my spreadsheet, so I used the first script to replace that function and it made all the difference. The second script is simply an archive script to move the row to an archive sheet. Only one will function at a time, no matter who I combine them. I've tried two separate scripts and I tried combining. Including changing the name of the function so. What am I missing?
function onEdit(e) {
if (e) {
var ss = e.source.getActiveSheet();
var r = e.source.getActiveRange();
// E.g. status column is 2nd (B)
status = ss.getRange(r.getRow(), 2).getValue();
// Specify the range with which You want to highlight
// with some reading of API you can easily modify the range selection properties
// (e.g. to automatically select all columns)
rowRange = ss.getRange(r.getRow(),3,1,8);
// This changes font color
if (status == 'Complete') {
rowRange.setFontColor("#d3d3d3");
rowRange.setBackgroundColor("#FFFFFF");
} else if (status == 'This Week') {
rowRange.setFontColor("#000000");
rowRange.setBackgroundColor("#ACE5A2");
} else if (status == 'Next Week') {
rowRange.setFontColor("#000000");
rowRange.setBackgroundColor("#D3D8D9");
} else if (status == 'Priority') {
rowRange.setFontColor("#FFFF11");
rowRange.setBackgroundColor("#1997F6");
} else if (status == 'Late') {
rowRange.setFontColor("#D92B14");
rowRange.setBackgroundColor("#FFFFFF");
} else if (status == '') {
rowRange.setFontColor("#000000");
rowRange.setBackgroundColor("#FFFFFF");
}
}
}
function onEditArchive() {
var sheetsToWatch= ["Valley","DBWC","Genus Heart","Mutli
Run","ECM","MRE","Medella","Mitro"];
var columnNumberToWatch = 10; // column A = 1, B = 2, etc.
var valueToWatch = "Archive";
var sheetNameToMoveTheRowTo = "Archive";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if (sheetsToWatch && range.getColumn() == columnNumberToWatch &&
range.getValue() == valueToWatch) {
var targetSheet = ss.getSheetByName(sheetNameToMoveTheRowTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1,
1);
sheet.getRange(range.getRow(), 1, 1,
sheet.getLastColumn()).moveTo(targetRange);
sheet.deleteRow(range.getRow());
}
}
Got an answer from Two OnEdit functions not working together
In short, I renamed the second OnEditArchive to OnEdit2 and then went to Edit > Current Project Triggers and set up each individual OnEdit to be triggered on edit.
Hope that helps!