Google Sheets onEdit moving rows between sheets with different columns - google-apps-script

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)

Related

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,

Move row based on cell selection

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.

How do I copy data from one row in a google sheet to another tab in the same sheet?

To expand on the surface level detail of my question; I have one google sheet tab which updates automatically with data each Monday. What I need to be able to do is copy that row from it's tab within the Google Sheet to another tab within the same over arching sheet. This copied row needs to be placed one down from the previous row (week 1 would be row 1, week 2 row 2 etc).
So far I have set up a trigger for this script to run each Monday (so I've managed the easy part...) but I still cannot figure out how to do the main body of work! I've had a look at some similar bits of code (one of which I've pasted down below) where data gets moved across to a new sheet when a box is ticked or when a certain value is noticed in a cell, but I couldn't modify either of these to work in my case.
I'm completely new to using Google Script and with no background in any language so help on this would be amazing! Or if anybody knows a way of performing this function without the need of Script that would be even better! (I've looked into using =today() and using the dates i would be looking for as triggers, but of course that comes up with an error as the text of the cell is '=today()' and not the actual date...)
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 colu 4 or D
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "main" && r.getColumn() == 4 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Completed");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
} else if(s.getName() == "Completed" && r.getColumn() == 4 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("main");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.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);

Make an onEdit script read other columns to determine where to send data based on edits

This script currently works, but I would like to add the ability to read data in Column A of Sheet1 (usernames) so that the row is moved to the corresponding sheet. For instance, if "Jim" is the username listed in Column A, the script will send the row to "Jim's" Sheet. There will be 9 different users on this sheet and I would like to move away from everyone viewing the "Master" tab so to speak.
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (s.getName() == "Sheet1" && r.getColumn() == 2 && r.getValue() == "Yes") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Sheet2");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}