Move row to new tab after sheet updates automatically - google-apps-script

I need to move rows from a tab based on a cell including "lep". The problem is that it doesn't read the info already on the sheet when it's opened (since it is a sheet that automatically updates new sales from Shopify via Zapier).
What would be the solution for this? I tried onEdit & onOpen already and neither work.
function onOpen(e) {
// assumes source data in sheet named SHOPIFY
// target sheet of move to named ORG
// test column with yes is col 17 or Q
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = e.source.getActiveSheet();
var r = e.source.getActiveRange();
if(s.getName() == "SHOPIFY" && r.getColumn() == 17 && r.getValue().includes("lep")) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("ORG");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}

function moveRows() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('SHOPIFY');
const tsh = ss.getSheetByName('ORG')
const vs = sh.getDataRange().getValues();//you may wish to change the range to not include headers
let d=0;
vs.forEach((r,i)=>{
if(r[16].toString().includes("lep")) {
tsh.appendRow(r);
sh.deleteRow(i+1-d++);
}
});
}
function onMyOpen() {
//needs installable trigger
moveRows();
}

An onEdit() simple trigger will only run when the user hand edits the spreadsheet.
An onOpen() simple trigger will only run when you open the spreadsheet in a web browser, and its event object does not include information about any recent changes in the spreadsheet.
To detect changes made by Zapier you will need an on change installable trigger. See the moveRowsFromSpreadsheetToSpreadsheet_ script for an example of how to do that.

Related

Run Google appscript on change of dropdonw

I am very new to Google Appscript and support of this community will really be appreciated. Using different posts on the Stakeoverflow community I had designed an appscript to copy and paste the data from one worksheet to another and this is working fine (the data of worksheet named Copy is paste in worksheet named Paste). I had also created a worksheet named Trigger and in that I had created a dropdown in cell A1, now I want my script to run every time when the dropdonw in this sheet is changed. I had checked the different solutions on this community but as am new to appscirpt could not design a perfect solution to my case. Below is the link to the sheet and my current script.
https://docs.google.com/spreadsheets/d/1xy5eN8_PHXi9RPWK_EKg99dylaDjQ9lcilrSW0GP4B0/edit#gid=0
function Referesh() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Copy");
var pasteSheet = ss.getSheetByName("Paste");
var source = copySheet.getRange(2,1,copySheet.getLastRow(),2);
var rub = copySheet.getRange(2,1,copySheet.getLastRow(),2);
var destination =
pasteSheet.getRange(pasteSheet.getLastRow()+1,2,copySheet.getLastRow(),2);
source.copyTo((destination), {contentsOnly: true});
rub.clearContent();
console.log(pasteSheet.getLastRow());
}
Any help on above will be appreciated.
I believe your goal is as follows.
You want to automatically run your script by changing the dropdown list of the cell "A1" of "Trigger" sheet.
In this case, how about using the OnEdit simple trigger as follows?
Modified script:
Please copy and paste the following script to the script editor of Spreadsheet and save the script. When you use this script, in this case, please change the dropdown list of the cell "A1" of "Trigger" sheet to "Run". By this, the script is run.
function onEdit(e) {
var sheetName = "Trigger";
var runScript = "Run";
var { range, source, value } = e;
var sheet = range.getSheet();
if (sheet.getSheetName() != sheetName || range.columnStart != 1 || range.rowStart != 1 || value != runScript) return;
var ss = source;
var copySheet = ss.getSheetByName("Copy");
var pasteSheet = ss.getSheetByName("Paste");
var source = copySheet.getRange(2, 1, copySheet.getLastRow(), 2);
var rub = copySheet.getRange(2, 1, copySheet.getLastRow(), 2);
var destination = pasteSheet.getRange(pasteSheet.getLastRow() + 1, 2, copySheet.getLastRow(), 2);
source.copyTo((destination), { contentsOnly: true });
rub.clearContent();
console.log(pasteSheet.getLastRow());
range.setValue("Refresh"); // By this script, the value of "Run" is changed to "Refresh".
}
Note:
It seems that there are 2 values of Run and Refresh in your dropdown list. Unfortunately, I couldn't know the trigger value. So, in this sample script, when the dropdown list is changed to Run, the script is run by the simple trigger. If you want to change this, please modify the above script.
When you run directly onEdit with the script editor, an error occurs because of no event object. So, please be careful about this.
If you want to ignore the trigger value, I think that the following script might be able to be used. In this case, the dropdown list is changed, the script is run.
function onEdit(e) {
var sheetName = "Trigger";
var { range, source } = e;
var sheet = range.getSheet();
if (sheet.getSheetName() != sheetName || range.columnStart != 1 || range.rowStart != 1) return;
var ss = source;
var copySheet = ss.getSheetByName("Copy");
var pasteSheet = ss.getSheetByName("Paste");
var source = copySheet.getRange(2, 1, copySheet.getLastRow(), 2);
var rub = copySheet.getRange(2, 1, copySheet.getLastRow(), 2);
var destination = pasteSheet.getRange(pasteSheet.getLastRow() + 1, 2, copySheet.getLastRow(), 2);
source.copyTo((destination), { contentsOnly: true });
rub.clearContent();
console.log(pasteSheet.getLastRow());
}
Reference:
Simple Triggers

Run a function with onEdit on Google Sheets mobile app

I made my function that it's working good for me now, but i have the issue to make it work on mobile so i tried another way to use the function OnEdit, so when it will be the value that i want to lunch the function that i created before, but for now it's not working and i don't know why it's not, i'm asking for you help with this small issue ;)
thank you
function onEdit(e) {
var range = e.range;
var spreadSheet = e.source;
var sheetName = spreadSheet.getActiveSheet().getName();
var column = range.getColumn();
var row = range.getRow();
var value = SpreadsheetApp.getActiveSheet().getRange(row, column).getValue();
if(sheetName == 'New Orders' && column == 12 && value=='COMMANDE VALIDER')
{
VALIDERCOMMANDE();
}
}
function VALIDERCOMMANDE() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("New Orders");
var url = "https://docs.google.com/spreadsheets/d/1eTWG_XZt-3CMzkxgKM4pCvD41deGMdka37eQkHM9oDg/edit#gid=0";
var ss2 = SpreadsheetApp.openByUrl(url);
var pasteSheet = ss2.getSheetByName("Order Pull");
// get source range
var max = copySheet.getMaxRows().toString();
var range = copySheet.getRange(2, 1, max, 12);
var dataValues = range.getValues();
for (i = 1; i < dataValues.length; i++) {
if (dataValues[i][11] === 'COMMANDE VALIDER') {
pasteSheet.appendRow([dataValues[i][0],
dataValues[i][1],
dataValues[i][2],
dataValues[i][3],
dataValues[i][4],
dataValues[i][5],
dataValues[i][6],
dataValues[i][7],
dataValues[i][8],
dataValues[i][9],
dataValues[i][10],
dataValues[i][11]]);
var clearRow = i + 2;
copySheet.getRange('D' + clearRow + ':L' + clearRow).clearContent();
}
}
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow() + 1, 1, max, 1);
// clear source values
Browser.msgBox('Commande Confirmer');
}
Try this way
function onMyEdit(e) {
const sh = e.range.getSheet();
if (sh.getName() == 'New Orders' && e.range.columnStart == 12 && e.value == 'COMMANDE VALIDER') {
VALIDERCOMMANDE();
}
}
function VALIDERCOMMANDE() {
var ss = SpreadsheetApp.getActive();
var csh = ss.getSheetByName("New Orders");
var id = "1eTWG_XZt-3CMzkxgKM4pCvD41deGMdka37eQkHM9oDg";
var ss2 = SpreadsheetApp.openById(id);
var psh = ss2.getSheetByName("Order Pull");
var vs = csh.getRange(2,1,csh.getLastRow() - 1, 12).getValues().filter(r => r[11] == 'COMMANDE VALIDER').filter(e => e);
psh.getRange(psh.getLastRow() + 1, 1, vs.length, 12).setValues(vs);
}
I often find that onEdits are not reliable on mobile and sometimes the trigger process has to be repeated
Class Browser, Class UI and SpreadsheetApp.toast don't work in the Google Sheets mobile apps (iOS and Android). By the other hand, instead of using a simple trigger you should use an installable trigger because SpreasheetApp.openByUrl method requires authorization to run.
Change the name of the onEdit function, remove Browser.msgBox('Commande Confirmer'); and create an installable on edit function calling the renamed function should make your script work on the mobile apps
If you really need to have a custom notification when the onEdit function finish, you might send write a message or image on certain range. If you use on edit installable trigger you might also send an email or call an external API.
Related
Executing Google Apps Script Functions from Mobile App
Google Apps Script toast messages don't appear for anonymous editors
why is my trigger status "Paused" when triggered from mobile

Moving Rows from one sheet to another based on selected values

I have an Apps Script I am using to move rows from one tab on my sheet to another based on what I select in a specific column.
The code I am using seems to work however it is putting two copies of the line on the second sheet I am pretty new to app script so i may have made an error in the code. I litterally just need the row to move over and delete from the original page.
function onEdit(e){
var sourceSheet = e.range.getSheet();
var row = e.range.getRow();
if(sourceSheet.getSheetName() === 'Submissions'){
var rowRange = sourceSheet.getRange(row, 1, 1, sourceSheet.getLastColumn());
var rowValues = rowRange.getValues()[0];
if(rowValues[16] === "Approved"){
var targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Completed");
targetSheet.appendRow(rowValues);
sourceSheet.deleteRow(row);
}
}
}
Delete Selected Rows
function onEdit(e) {
var sh = e.range.getSheet();
if(sh.getName() == 'Submissions'){
var rowRange = sh.getRange(e.range.rowStart, 1, 1, sh.getLastColumn());
var rowValues = rowRange.getValues()[0];
if(rowValues[16] == "Approved"){
var tsh = e.source.getSheetByName("Completed");
tsh.appendRow(rowValues);
sh.deleteRow(e.range.rowStart);
}
}
}
Perhaps you create and installable trigger with the name onEdit. In this case you are getting two triggers. One the installable version and one from the simple trigger. I also rewrote the function taking advantage of event object.

Write remotely to another googlesheet

I have the function below I have copied from somewhere else. It basically moves a row you would have completed to another sheet in the same file (moves from sheet Origin to Target, Trigger is "Move").
What I would like to achieve is to be able to move that completed row to another google sheet file instead of another sheet in the same file. I have tried SpreadsheetApp.openByUrl and SpreadsheetApp.openByID, but nothing happens, I was expecting some permission request etc. but nothing, not even an error.
Can someone help me with this?
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Origin" && r.getColumn() == 10 && r.getValue() == "Move") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Target");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, (numColumns-1)).moveTo(target);
s.deleteRow(row);
}
I believe your goal as follows.
You want to copy the values of s.getRange(row, 1, 1, (numColumns-1)) to the last row of Target sheet in other Spreadsheet.
You want to run the script by OnEdit event trigger.
For this, how about this answer?
Modification points:
In order to use SpreadsheetApp.openByUrl and SpreadsheetApp.openByID, it is required to use the installable OnEdit event trigger instead of the simple trigger of OnEdit event trigger. When SpreadsheetApp.openByUrl and SpreadsheetApp.openByID are run with the simple trigger, an error related to the permission occurs.
I think that the reason of your issue is this.
When the values are moved to other Spreadsheet, move() cannot be used. So in this case, getValues and setValues are used.
When above points are reflected to your script, it becomes as follows.
Modified script:
Please copy and paste the following script. And, please install the OnEdit event trigger to the function of installedOnEdit as the installable trigger. By this, when the cell is edited, SpreadsheetApp.openById is run.
function installedOnEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Origin" && r.getColumn() == 10 && r.getValue() == "Move") {
var id = "###"; // Please set the Spreadsheet ID.
var dst = SpreadsheetApp.openById(id);
var targetSheet = dst.getSheetByName("Target");
var row = r.getRow();
var numColumns = s.getLastColumn();
var srcRange = s.getRange(row, 1, 1, (numColumns-1));
s.deleteRow(row);
targetSheet.getRange(targetSheet.getLastRow() + 1, 1, 1, numColumns - 1).setValues(srcRange.getValues());
}
}
References:
Simple Triggers
Installable Triggers

How to apply a Google Apps Script to an entire Google Sheets spreadsheet?

I'm trying to apply one script that will run on an entire Google Sheets spreadsheet, not just one tab. I have multiple tabs all with the same format; I want the script to look at the data validation in column F for every tab and if "Not Applicable" is selected for any row, move the contents of that entire row to a tab called "Not Applicable Items"
I have no experience writing scripts, so I copied the script I'm currently using from a forum topic. It successfully moves the rows to the correct tab, but only for the specified active sheet. I want the script to look at the entire spreadsheet and move any row marked "Not Applicable."
How can I do this? Here's my code:
function onEdit() {
var sheetNameToWatch = "Floorplan + Calendars";
var columnNumberToWatch = 5; // column A = 1, B = 2, etc.
var valueToWatch = "Not Applicable";
var sheetNameToMoveTheRowTo = "Not Applicable Items";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if (
sheet.getName() == sheetNameToWatch &&
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());
}
All of the scripts in a given project have access to all of the sheets in the spreadsheet. Thats why we recommend that you write you onEdit(e) script like this:
function onEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()!="Sheet Name") return;
This limits the script from performing operations on unwanted sheets.
However, in your case you want all sheets involved in the onEdit(e) function so this is not necessary.
Personally, I wouldn't run this function in an onEdit() function because it's liable to take longer than 30 seconds. But the functionality you requested is accomplished with the following script. exclA is an array of sheet names that you don't want to include in your "Not Applicable" search like the sheet named "Not Applicable Items".
function notApplicable() {
var ss=SpreadsheetApp.getActive();
var dsh=ss.getSheetByName('Not Applicable Items')
var exclA=["Not Applicable Items"];
var shts=ss.getSheets();
for(var i=0;i<shts.length;i++) {
var name=shts[i].getName();
if (exclA.indexOf(shts[i].getName())==-1) {
var sh=shts[i];
var rg=sh.getDataRange();
var vA=rg.getValues();
var d=0;
for(var j=0;j<vA.length;j++) {
if(vA[j][5]=="Not Applicable") {
dsh.appendRow(vA[j]);
sh.deleteRow(j+1-d++)
}
}
}
}
}
I think that a lot of users over use the onEdit() capability.
You can grab each spreadsheet in a for loop by doing
for(var i = 0; i < [number of sheets]; i++){
sheet = ss.getSheets()[i];
. . . [rest of the code]
}
and include what you're trying to do inside the for loop to do with each sheet.