Moving row to new sheet from drop down in Google Sheets - google-sheets

I'm trying to move new hires from a list of open positions in sheet "Open Roles" to "Hired" based on selecting the option "Hired" from a drop down list in column H/8 ("Stage"). I created asample doc here.
I'm new at this and put the below into script editor (that I got from another thread) but when I hit run it returns "TypeError: Cannot read property 'source' of undefined" and "Open Roles" appears red as if it doesn't recognize it.
Can anyone help identify what I'm doing wrong or missing please? Thanks so much in advance!
function onEdit(e) {
const src = e.source.getActiveSheet();
const r = e.range;
if (src.getName() != "Open Roles" || r.columnStart != 8 || r.rowStart == 1) return;
const dest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Hired");
src.getRange(r.rowStart,1,1,8).moveTo(dest.getRange(dest.getLastRow()+1,1,1,8));
src.deleteRow(r.rowStart);
}

However, remember the debugger is your friend. I suggest you set a variable to src.getName(), set a breakpoint to the following line and inspect the value.
var nme = src.getName();
If it is not the name of the tab then you know that is the issue.
Strange though, I made a copy of your sheet and it seems to move rows to the Hired tab. It moves any one that is changed though, not just of it is marked Hired.
I added an check to see if the value is "Hired"
function onEdit(e) {
const src = e.source.getActiveSheet();
const r = e.range;
if (src.getName() !== "Open Roles" || r.columnStart !== 8 || r.rowStart == 1) return;
const dest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Hired");
if (src.getRange(r.rowStart,8).getValue() == "Hired") {
src.getRange(r.rowStart,1,1,8).moveTo(dest.getRange(dest.getLastRow()+1,1,1,8));
src.deleteRow(r.rowStart);
}
}
I reworked the code a bit, not sure if it will solve the undefined error but it is cleaner, I prefer one return whenever possible.
function onEdit(e) {
const src = e.source.getActiveSheet();
const r = e.range;
var sheetName = src.getName();
if (src.getName() == "Open Roles" && r.columnStart == 8 && r.rowStart !== 1) {
const dest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Hired");
if (src.getRange(r.rowStart,8).getValue() == "Hired") {
src.getRange(r.rowStart,1,1,8).moveTo(dest.getRange(dest.getLastRow()+1,1,1,8));
src.deleteRow(r.rowStart);
}
}
}
This script does not rely on the object "e" passed to onEdit()
function onEdit(e) {
//const src = e.source.getActiveSheet();
const src = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Open Roles");
Logger.log(src);
var activeRange = src.getActiveRange();
const currRow = activeRange.getRowIndex();
const currCol = activeRange.getColumn();
Logger.log(currRow);
Logger.log(currCol);
var sheetName = src.getName();
if (src.getName() == "Open Roles" && currCol == 8 && currRow !== 1) {
const dest = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Hired");
if (src.getRange(currRow,8).getValue() == "Hired") {
src.getRange(currRow,1,1,8).moveTo(dest.getRange(dest.getLastRow()+1,1,1,8));
src.deleteRow(currRow);
}
}
}

Findings:
The reason why you're getting the TypeError: Cannot read property 'source' of undefined is because you can't run the onEdit(e) function directly from the Apps Script editor as it needs to pass data for the parameter e which will only happen when you perform an edit action on your sheet. You can view this explanation for more details.
Recommendation:
You can try & run this sample script instead without the parameter e:
function onEdit() {
var sheet = SpreadsheetApp.getActive();
var selectedCell = sheet.getActiveSheet().getCurrentCell().getA1Notation(); //Get selected cell location on Column H (in A1 notation)
var value = sheet.getActiveSheet().getRange(selectedCell).getValue(); //Get the selected value from dropdown
const dest = sheet.getSheetByName("Hired"); //The destination sheet
if(value.toString().includes("Hired")){ //Check if the selected value from the dropdown was "Hired"
var selectedRange = selectedCell.split(""); //Gets the range of the selected cell
Logger.log("\"Hired\" found on range "+ "A"+selectedRange[1]+":"+selectedCell); //Logs the result for review. Range starts in column A to H based on selected row number
sheet.getActiveSheet().getRange("A"+selectedRange[1]+":"+selectedCell).moveTo(dest.getRange(dest.getLastRow()+1,1,1,8));
SpreadsheetApp.getActiveSpreadsheet().toast("Done moving data from "+"A"+selectedRange[1]+":"+selectedCell+" to \"Hired\" sheet");
sheet.getActiveSheet().deleteRow(selectedRange[1]); //Delete the row of the selected cell from the "Open Roles" sheet
}else{
//Do nothing if the selected dropdown value is not "Hired"
}
}
RESULT:
Sample "Open Roles" sheet:
When H2 was set to "Hired," you'll see a toast message on "Open Roles" sheet:
Sample "Hired" sheet:
Here's the Execution Logs:

Related

Google Sheets connecting with Gmail or Slack

I'm looking for a code I can use in google sheets.
I need to get a notification when a cell changes in a specific column and get it through email or Slack.
Can someone please help me?
I'm currently using
function onSpeEdit(e) {
var sh = e.source.getActiveSheet();
var rng = e.source.getActiveRange();
var col = 1
if (sh.getName() == 'mySheet' && rng.getColumn() == col) {
MailApp.sendEmail(
'yourEmail#gmail.com',
`Change Notification`,
`Change in ${rng.getA1Notation()} old value "${e.oldValue}" new value "${e.value}" `);
}
}
Try
function onSpeEdit(e) {
var sh = e.source.getActiveSheet();
var rng = e.source.getActiveRange();
var col = 1
if (rng.getColumn() == col) {
MailApp.sendEmail(
'yourEmail#gmail.com',
`Change Notification`,
`Change in ${rng.getA1Notation()} of ${sh.getName()} old value "${e.oldValue}" new value "${e.value}" `);
}
}
change name of sheet, column and email address
you will need to define an installable trigger in order to use services that requires authorization.
Installable Triggers
edit : il you want to add another information, i.e. from column B, try to replace the sentence by
`Hey, the title ${sh.getRange('B'+rng.getRow()).getValue()} from sheet ${sh.getName()} changed. Before it has the number ${e.oldValue} now is ${e.value}.`

Google Sheets - Creating a button to run on a column selected by the user

I'd like to have a user click/highlight a column (or a checkbox at the top of the column, then click a single button to run the script on all checked columns.
var values1 = "Pass";
// Where to look for Auto:
var enabledDisabled = sheet.getRange("B3:B140").getValues();
var testResultsRange = sheet.getRange("AL3:AL140");
var testResults = testResultsRange.getValues();
// Keyword to look for in Auto: column
var putValues = [];
for (var i = 0; i < enabledDisabled.length; i++) {
if (enabledDisabled[i][0] === "Yes") {
putValues.push([values1]);
} else {
putValues.push([testResults[i][0]]); // Push the existing cell value
}
}
// Put value1 inside row, column# for test result
testResultsRange.setValues(putValues);
Instead of hardcoded ranges, I'd like it to run on every column that is checked, basically.
Any help would be hugely appreciated!
One solution I usually use is to put checkboxes on the first row of the columns, then with onEdit I run the script by clicking on the checkbox and by detecting the column by getColumn ()
function onEdit(event){
var sh = event.source.getActiveSheet();
var cel = event.source.getActiveRange();
if (sh.getName()=='mySheet' and cel.getValue()){
var col = cel.getColumn()
// run your script in column 'col'
cel.setValue(!cel.getValue())
}
}

How to run a Dynamic Script in Google Sheets (live edit)

I am trying to run a script that will execute when the checkbox is marked "TRUE" and send an email to a client. I can not get the triggers to work and I can seem to make my own work either. I am putting the code below. Please help.
'''code'''
***Email Function
function SendEmail(i) {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
//var lr= ss.getLastRow();
//for (var i = 2; i<=lr;i++){
var currentEmail= ss.getRange(i, 1).getValue();
//logger.log(currentEmail);
var currentADID= ss.getRange(i, 3).getValue();
MailApp.sendEmail(currentEmail,"Customer Ready"+ currentADID,"This customer should be ready to schedule and installtion date and time" );
}
Trigger Function
function CheckCD() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lr= ss.getLastRow();
for (var i = 2; i<=lr;i++){
var currentDCheck= ss.getRange(i, 4).getValue();
var x= onEdit():
if (currentDCheck == true)
SendEmail(i)
}
}***
You actually misunderstood how to use onEdit trigger, although you need to install the trigger in this case due to permission needed by MailApp.sendEmail
Anyways, you need to make use of the event object (e) as it holds the details about the edited cell's properties. See code below:
Code:
// Trigger function, install it under "Triggers" tab as you need permission for MailApp
function CheckCD(e) {
// get the row and column of the edited cell
var row = e.range.getRow();
var column = e.range.getColumn();
// proceed only if edited cell's range is D2:D and value is "TRUE"
if (row > 1 && column == 4 && e.value == "TRUE") {
// get the sheet where the cell was edited
var ss = e.source.getActiveSheet();
// get Email and ADID of the same row where checkbox was ticked
var currentEmail = ss.getRange(row, 1).getValue();
var currentADID = ss.getRange(row, 3).getValue();
MailApp.sendEmail(currentEmail, "Customer Ready" + currentADID, "This customer should be ready to schedule and installtion date and time");
}
}
Install trigger:
Make sure to choose On edit event type and choose the function you want to run. (in this case, CheckCD)
Sample data:
Output:
Note:
The behavior of this script is that every time someone checks a checkbox on range D2:D and the resulting value is TRUE, then it sends an email. (as it seems you have different email per row, but if not, send them all in one email)
References:
Installable Triggers

Inserting Timestamp in Google Spreadsheet

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.

Google sheets- loop search column, select tow

I have a google spreadsheet that i have one last problem i cant seem to solve.
i added a button to this script, and when i press the button it triggers the AddClient function.
How can i make the script below loop down all rows in column 3 searching for the yes value, when it finds it, copy the row below it to sheet "client" and then stop?
function AddClient(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "SETUP" && r.getColumn() == 3 && r.getValue() == "yes") {
var row = r.getRow() + 1; // Add 1 to the active row
var targetSheet = ss.getSheetByName("client");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 2, 1, 4).copyTo(target, {contentsOnly:true}); //Only selecting column 2, then the following 4 columns
}
}
Edit*
Example document:
https://docs.google.com/spreadsheets/d/1DFbAp0IN8_UFv9u8kWiZBTxDogj4e7FnuAPzC0grDw0/edit?usp=sharing
Any help greatly appreciated!
Cheers,
Reiel
Since you have a static form the position of the informatin to be copied will not change
Since we know we want to copy over the data we won't need to do any validation of where we are so all of that stuff can go
Sheets have an appendRow method that take care of the bookkeeping involved with finding the last row
This allows us to simplify the script to the following:
function AddClient() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getSheetByName("SETUP").getRange(25, 2, 1, 4).getValues()[0];
ss.getSheetByName("client").appendRow(data);
}
Edit:
To remove duplicates you could do the following:
function AddClient() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getSheetByName("SETUP").getRange(25, 2, 1, 4).getValues()[0];
var clients = ss.getSheetByName("client").getDataRange().getValues();
if (!clients.filter(function(row) {return data.join("|") === row.join("|");})) {
ss.getSheetByName("client").appendRow(data);
}
}
Note that for the particular example there are some problems because the leading zero gets cut off. Sheets is a bit weird and sometimes tries to force the format to be a number even when you set the cells' formats to Text...

Resources