Move row based on cell selection - google-apps-script

I have a script that moves the whole row to a different tab and deletes it from the tab it was moved based on a "list" selection.
The script is the following:
// Script Move & Delete
function onEdit(event) {
// assumes source data in sheet named Needed
// target sheet of move to named Acquired
// test column with yes/no is col 4 or D
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
// In Review Trigger
if(s.getName() == "Applied" && r.getColumn() == 1 && r.getValue() == "In Review") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("In Review");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
// In Review Trigger
else if(s.getName() == "Applied" && r.getColumn() == 1 && r.getValue() == "Failed") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Failed");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
So for example, if the row on Tab "Applied" and value of cell on column 1 = In Review then the row is moved to tab "In Review" but if the value of cell on column one = to Failed then row is moved to tab Failed.
That part works like charm and I know having multiple tabs will have a lot of else ifs, I'm not much of a dev, so I was wondering how can I do to move the row if the status (Column 1) is changed to Applied is moved to tab one or failed tab if value is changed to failed?
Basically, move the rows between tabs based on value of column one of each row/tab.
Thanks in advance!

This worked for me:
function onMyEdit(e) {
//e.source.toast('entry');
const s = e.range.getSheet();
if (s.getName() == "Sheet1" && e.range.columnStart == 1 && e.value) {
//e.source.toast('cond')
const names = ['Sheet2', 'Sheet3'];
let idx = names.indexOf(e.value);
if (~idx) {
//e.source.toast('sheet');
let tsh = e.source.getSheetByName(names[idx]);
let tgt = tsh.getRange(tsh.getLastRow() + 1, 1);
s.getRange(e.range.rowStart, 1, 1, s.getLastColumn()).moveTo(tgt);
s.deleteRow(e.range.rowStart);
}
}
}
I made some name changes to make it easier for me to debug so look it over to make sure all of the sheet names are right for your needs.

If you require more complex functionality in moving rows, take a look at the moveRowsFromSpreadsheetToSpreadsheet_ script. It is unfortunately too long to quote here directly.

Related

How can I find a sheet name by looking up a column

I'm very new to scripts (i.e a total novice).I'm trying to update a work tracker used by several members of a team. It basically logs cases on a separate tab for each person.
I have managed to set up a code that moves a row to another tab when a checkbox is ticked (i.e. when a case is closed they can automatically move the row of data to a "Closed" tab).
What I'm having trouble with is giving the team the option of moving it back should they close it in error. I can make it work but it only moves the data back to the named sheet in the script. How do I get it to find the sheet name by looking up the agent's name? The agents name is listed in column D.
Here is the code I've used this is where I believe I need the help:
var targetSheet = ss.getSheetName("Bob");
Many thanks
Loz
function onEdit(event) {
// assumes source data in sheet named main
// target sheet of move to named Completed
// getColumn with check-boxes is currently set to column 5 or E
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Bob","Billy","Anna","Emma","Joe" && r.getColumn() == 5 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Closed");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
} else if(s.getName() == "Closed" && r.getColumn() == 5 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetName("Bob");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
enter image description here
enter image description here
Getting sheet name from agent's column in sheet Closed I think
Assumed header row is one and Agent's column name is Agent
function onEdit(e) {
//e.source.toast("Entry");
//Logger.log(JSON.stringify(e));
const sh = e.range.getSheet();
const names = ["Bob", "Billy", "Anna", "Emma", "Joe"];
const idx = names.indexOf(sh.getName());
if (~idx && e.range.columnStart == 5 && e.value == "TRUE") {
//e.source.toast('Flag1');
var tsh = e.source.getSheetByName("Closed");
var trg = tsh.getRange(tsh.getLastRow() + 1, 1);
sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).moveTo(trg);
sh.deleteRow(e.range.rowStart);
} else if (sh.getName() == "Closed" && e.range.columnStart == 5 && e.value == "FALSE") {
//e.source.toast("Flag2");
let hA = sh.getRange(1, 1, 1, sh.getLastColumn()).getValues().flat();
//Logger.log(JSON.stringify(hA));
let col = {};
hA.forEach((h, i) => { col[h] = i + 1; });
//Logger.log(JSON.stringify(col));
//Logger.log(sh.getRange(e.range.rowStart, col["Agent"]).getDisplayValue());
var tsh = e.source.getSheetByName(sh.getRange(e.range.rowStart, col["Agent"]).getDisplayValue());
var trg = tsh.getRange(tsh.getLastRow() + 1, 1);
sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn()).moveTo(trg);
sh.deleteRow(e.range.rowStart);
}
}
If you wish a better answer then please provide image of Closed and one of the Named Sheets
I'm assuming you are unchecking a checkbox in column E in the "Closed" sheet and want to move the row back to the original agent. And the name of the agent or sheet name is in column D of that row. Then you can do this.
let agent = e.range.offset(0,-1).getValue();
let targetSheet = ss.getSheetName(agent);
Reference
Range.offset()

When I archive a row in another sheet in Google Sheets, it's deleting this row and the next one from the source sheet

My goal: by ticking a checkbox, I want to archive an entire row from source sheet (Leads) to the target sheet (Archive), same to unarchive from the target to the source sheet. I'm using this code for +1 year and never faced the kind of issue I'm having.
1st issue: When I tick the box for row X in the source sheet:
It's deleting the row X and row Y from the source sheet
Just row Y is moved and stored to the target sheet -> I don't know where row X goes.
2nd issue: When I try to unarchive row Y (even if it should be row X), nothing happens.
My code is:
// Variables defined in an onEdit(event) function
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
// Archive a project with checked box to Archive Sheet
if(s.getName() == "Leads" && r.getColumn() == 2 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Archive");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
// Unarchive a project from Archive sheet to respective owner
if(s.getName() == "Archive" && r.getColumn() == 2 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Leads");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
I tried to debug the code but I can't find my mistake.
Thank you for your help,

Google Sheets onEdit moving rows between sheets with different columns

I'm trying to create a simple shipment processing flow and want to move rows between two sheets(tabs) using an onEdit checkbox trigger.
Here's a link to my project: https://docs.google.com/spreadsheets/d/1SPO21kAyNX5fEqwkXVjmPASkfHvZ5Tzbq4s7e22VdYg/edit#gid=2005756436
The basic concept is that shipments made up of multiple pieces are input on the first sheet and then copied to the WB_Log sheet. When planning what to load into a truck, a checkbox is used to move the pieces from the WB_Log sheet to the Load_Plan sheet where their loading location will be determined in a column to the right of the checkbox. If a piece or pieces of a shipment will not fit in a particular truck, I want to uncheck the box on Load_Plan and have the row moved back to the WB_Log Sheet.
Here is the onEdit function I found that almost works:
function onEdit(event) {
// assumes source data in sheet named WB_Log
// target sheet of move to named Load_Plan
// getColumn with check-boxes is currently set to column 14 or N
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "WB_Log" && r.getColumn() == 14 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Load_Plan");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
} else if(s.getName() == "Load_Plan" && r.getColumn() == 14 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("WB_Log");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
My issue is that Load_Plan has columns to the right of the checkbox that I don’t want moved back to WB_Log. How do I adjust the code so that only the information from columns A:N move from Load_Plan back to WB_Log when the checkbox is unchecked (False)?
Any advice or ideas anyone can lend would be very much appreciated.
Modification points:
When I saw your shared Spreadsheet, "WB_Log" sheet has the checkboxes in the column "N". And the checkboxes are put to the bottom of the sheet. By this, targetSheet.getLastRow() + 1 returns the next row of the buttom of sheet. I think that this is the reason of your issue.
I think that in your situation, when the last row of after row of "B4" is retrieved, the row number can be used.
And, in your script, the columns "A" to "O" in "Load_Plan" sheet are retrieved by var numColumns = s.getLastColumn(). But "WB_Log" sheet has the columns "A" to "N". I think that the retrieved columns are required to be reduced 1 column.
When above points are reflected to your script, it becomes as follows.
Modified script:
Please modify your script as follows.
From:
} else if(s.getName() == "Load_Plan" && r.getColumn() == 14 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("WB_Log");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
To:
} else if(s.getName() == "Load_Plan" && r.getColumn() == 14 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn() - 1; // Modified
var targetSheet = ss.getSheetByName("WB_Log");
var lastRow = targetSheet.getRange("B4").getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow(); // Added
var target = targetSheet.getRange(lastRow + 1, 1); // Modified
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
Reference:
getNextDataCell(direction)

Google Sheets - How can I move a row to another sheet based on multiple criteria?

I am trying to move a row from sheet "Loads" to sheet "Invoiced Loads" based on multiple criteria. The criteria is:
If the load has been Delivered and Invoiced (which is a number greater than 0) move the load/row to sheet "Delivered".
I have seen many people have asked this question and I found a code that works, but only with one criteria. I have tried to modify the code so it checks the two conditions but I can not make it work. I ran out of options. Please if someone can help me I will really appreciate it. I know the solution must be really simple but I am a beginner on this and I am not sure which path to take please!!. The code I got at the moment is the below:
function onEdit(event) {
// assumes source data in sheet named Loads
// target sheet of move to named Invoiced Loads
// test column with "Delivered" is, col 19 or S
// test column with invoice number is, col 27 or AA
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if((s.getName() == "Loads" && r.getColumn() == 19 && r.getValue() == "Delivered") &&
(s.getName() == "Loads" && r.getColumn() == 27 && r.getValue() > 0)) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Invoiced Loads");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
Explanation:
The main issue with the if statement is that r.getColumn() can't be
19 and 27 at the same time but also r.getValue() can't be
"Delivered" and >0 at the same time. As a result, the if
condition will always evaluate to false.
Also you don't need to evaluate twice for the same condition. The if
condition in your code evaluates twice the expression s.getName() == "Loads" which is unnecessary. One is enough.
This is an onEdit function which means that every time you make a
change, event.range.getRow() and event.range.getColumn() will
give you the coordinates of the cell that was edited. There is no
need of using event.source.getActiveRange();.
Solution:
function onEdit(event) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const row = event.range.getRow();
const col = event.range.getColumn();
const as = event.source.getActiveSheet();
const numColumns = as.getLastColumn();
const targetSheet = ss.getSheetByName("Invoiced Loads");
const target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
if(as.getName() == "Loads" && as.getRange(row,19).getValue() == "Delivered"
&& as.getRange(row,27).getValue() >0) {
as.getRange(row, 1, 1, numColumns).moveTo(target);
as.deleteRow(row);
}
}

Have a specific cell move to a different tab rather than the entire row

I am super novice and wanted to get someone's input on how to make this work. I have been looking around and this has been the main topic. Which would send an ENTIRE row to another tab as the destination tab. But how to do you specify only to have one cell's information to the next tab. For example, I have names on Column A and I would only like to send the name and none of the information after that to the next google sheet tab once I get the value true.
function onEdit(event) {
// assumes source data in sheet named main
// target sheet of move to named Completed
// getColumn with check-boxes is currently set to column 4 or D
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Interviewer Training" && r.getColumn() == 16 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("General IC SWE");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
} else if(s.getName() == "General IC SWE" && r.getColumn() == 16 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Interviewer Training");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1;
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
To move a single cell value from the current sheet to the next sheet.
function onEdit(e) {
//e.source.toast('flag1');
var sh=e.range.getSheet();
var idx=sh.getIndex();
var tsh=nextSheet(e);
//e.source.toast('Next Sheet: ' + tsh.getName());
if(sh.getName()!="Sheet1")return;
if(e.range.columnStart==1 && e.value=='TRUE' && !e.range.offset(0,1).isBlank() ) {
//e.source.toast('flag2');
tsh.getRange(e.range.rowStart,e.range.columnStart + 1).setValue(e.range.offset(0,1).getValue());
}
}
function nextSheet(e) {
//e.source.toast('flag3');
var sh=e.range.getSheet();
var shts=e.source.getSheets();
return shts[(sh.getIndex())%shts.length];
}
This is my sheet 1:
This is the next sheet:
I'm using the click of a checkbox to trigger the onEdit() function to make the transfer of the data immediately to the right of the selected check box and I move it to the same cell in the next sheet. The next sheet is the sheet immediately to the right or if it's the last sheet on the right it moves to the first sheet.
Sheet.getIndex()
Remainder or Modulo Operator
To move just a single cell you would only need to change your s.getRange()
s.getRange(row, 1, 1, numColumns).moveTo(target);
To get cell in row X column B
s.getRange(row, 2, 1, 1).moveTo(target);
The get range uses these parameters;
.getRange(Row Number, Column Number, Number of Rows, Number of Columns)
You only need to edit Column Number and Number of Columns
So row X column C & D would be
s.getRange(row, 3, 1, 2).moveTo(target);