Write remotely to another googlesheet - google-apps-script

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

Related

Is there a way for me to use the 1st cell of a row as a getsheetbyname parameter in google sheet?

function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Sheet1" && r.getColumn() == 3 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("id1");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
// s.deleteRow(row);
}
}
This is the code so far and I was wondering if there was a way for me to automatically append all of the row or "id" to their specific tab if their checkbox have been checked using the 1st cell of the row as the parameter for the getsheetbyname?
I tried to create a variable and put it in the getSheetByName() like the example below but it didn't work. I'm very new to javascript/apps script.
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Sheet253" && r.getColumn() == 2 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var a = row[0];
var targetSheet = ss.getSheetByName(a);
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
// s.deleteRow(row);
}
}
This is an example of the google sheet:
https://docs.google.com/spreadsheets/d/19TzSKyY4616sWpY2ONPj01F5CJDfsTJ7DmbFXPVKvJE/edit?usp=sharing
The result should look like the result in tab id1.
Modification points:
In your script, I thought that the event object can be used.
In your sample Spreadsheet, it seems that the checkbox is put to the column "C". When you want to run the script, when the checkbox is checked, the checked column is the column "C".
When these points are reflected in your script, how about the following modification?
Modified script:
From your provided sample Spreadsheet, this script supposes that the source sheet name is "Sheet1". Please be careful about this.
function onEdit(event) {
var ss = event.source;
var s = ss.getActiveSheet();
var r = event.range;
if (s.getName() == "Sheet1" && r.columnStart == 3 && r.isChecked()) {
var sheetName = r.offset(0, -2).getValue();
var targetSheet = ss.getSheetByName(sheetName);
if (!targetSheet) {
Browser.msgBox(`"${sheetName}" was not found.`);
return;
}
var row = r.rowStart;
var numColumns = s.getLastColumn();
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
// s.deleteRow(row);
}
}
In this script, when the checkbox of the column "C" of "Sheet1" is checked, the row is copied.
Note:
In your showing script, the edited row is used. So I modified your script by following your showing script. But, about This is the code so far and I was wondering if there was a way for me to automatically append all of the row or "id" to their specific tab if their checkbox has been checked using the 1st cell of the row as the parameter for the getsheetbyname?, if you want to copy all rows by one execution of the script, how about the following sample script? When this script is run, the checkboxes of column "C" of "Sheet1" are checked, and each value are copied to each sheet using the values of column "A".
function sample() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const srcSheet = ss.getSheetByName("Sheet1");
const obj = srcSheet.getRange("A2:C" + srcSheet.getLastRow()).getValues().reduce((o, r) => {
if (r[2] === true) {
o[r[0]] = o[r[0]] ? [...o[r[0]], r] : [r];
}
return o;
}, {});
Object.entries(obj).forEach(([name, values]) => {
const sheet = ss.getSheetByName(name);
const range = sheet.getRange(sheet.getLastRow() + 1, 1, values.length, values[0].length);
range.setValues(values).offset(0, 2, values.length, 1).insertCheckboxes();
});
}
Note:
This sample script is for your provided sample Spreadsheet. So, when you change the structure of the Spreadsheet, the script might not be able to be used. So, please be careful about this.
References:
Event Objects
getValues()
setValues(values)

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.

Move row to new tab after sheet updates automatically

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.

Modify Code - Copy Range to another Spreadsheet Google Sheets

The code below copies range and moves to next Spreadsheet in same workbook called "Topup Required".
I would like it to send this data to another spreadsheet inside another workbook instead.
function onEdit(event) {
// assumes source data in sheet named PrepSheet
// target sheet of move to named TOP UP NEEDED
// getColumn with check-boxes is currently set to column I
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "PrepSheet" && r.getColumn() == 9 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("TOP UP NEEDED");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
}
}
I tried replacing
var targetSheet = ss.getSheetByName("TOP UP NEEDED");
with
var targetSheet = SpreadsheetApp.openById("sheet ID").getSheetByName("TOP UP NEEDED");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
but it didnt work
Could anyone tell me where i went wrong
Thanks
You want to copy the values and format from s.getRange(row, 1, 1, numColumns) to the last row on the sheet of TOP UP NEEDED in the Spreadsheet of sheet ID, when the cell is edited.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification point:
Unfortunately, in the current stage, copyTo() of Class range cannot be used for other Spreadsheet.
Pattern 1:
In this pattern, copyTo() is used. So both the values and the cell format are copied.
Modified script:
When your script is modified, please modify as follows.
From:
var targetSheet = ss.getSheetByName("TOP UP NEEDED");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
To:
var targetSS = SpreadsheetApp.openById("sheet ID");
s = SpreadsheetApp.getActiveSheet();
var tempSheet = s.copyTo(targetSS);
var targetSheet = targetSS.getSheetByName("TOP UP NEEDED");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
tempSheet.getRange(row, 1, 1, numColumns).copyTo(target);
targetSS.deleteSheet(tempSheet);
Pattern 2:
In this pattern, getValues() and appendRow() are used. So only the values are copied.
Modified script:
When your script is modified, please modify as follows.
From:
var targetSheet = ss.getSheetByName("TOP UP NEEDED");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
To:
var targetSheet = SpreadsheetApp.openById("sheet ID").getSheetByName("TOP UP NEEDED");
var sourceValues = s.getRange(row, 1, 1, numColumns).getValues()[0];
targetSheet.appendRow(sourceValues);
Note: IMPORTANT
In this modification, the simple trigger of onEdit() cannot be used. An error occurs at openById(). So please use the installable trigger of OnEdit event trigger. In this case, please modify the function name as follows.
From
function onEdit(event) {
To
function installedOnEdit(event) {
After this modification, please install the OnEdit event trigger to installedOnEdit as the installable trigger. By this, when the cell is edited, installedOnEdit is run without the double executions. Please be careful this.
References:
copyTo(destination) of Class Range
copyTo(spreadsheet) of Class Sheet
getValues()
appendRow(rowContents)
Simple Triggers
Installable Triggers
If I misunderstood your question and this was not the direction you want, I apologize.

Need to move row from one google spreadsheet to a completely different google spreadsheet

I am trying to move a row from one spreadsheet to a completely different spreadsheet based on a cell. I have a script that I can make work if the sheets are in the same file but not two different files. The first file was created by a form responses and the other file is a spreadsheet I manually created. Here is my script:
function onEdit() {
var sheetNameToWatch = "Form Responses 1";
var columnNumberToWatch = 11;
var valueToWatch = "Y";
var sheetNameToMoveTheRowTo = "Completed Repairs";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ts = SpreadsheetApp.openById("1VpSqsR_zBU6FhEfVW5QJi2-oAvVhxnxSQmoINz_J5-Y");
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch && range.getValue() == valueToWatch) {
var targetSheet = ts.getSheetByName(sheetNameToMoveTheRowTo);
var targetRange = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
sheet.getRange(range.getRow(), 1, 1,sheet.getLastColumn()).copyTo(targetRange);
sheet.deleteRow(range.getRow());
}
}
You are seeing this error Execution failed: You do not have permission to perform that action., because you cannot call Built-in Google Services(openById) from onEdit() function.
Simple triggers run in a limited auth mode that doesn't allow opening other spreadsheets. You can create an installable trigger (details in that help page) to run your onEdit script with full auth.
Check this page for more details on simple triggers and the restrictions for the triggers.
Hope that helps!