Can't get getActiveSheet() from undefined - google-apps-script

I'm trying to copy a row from sheet "Name1" to sheet "Name2" when entering "ok" in cell 1 (column 1) but I couldn't fix this error in the title (Cannot call method "getActiveSheet" from undefined). I have tried all those commented lines but no luck, I'm editing the cell and enter "ok" in that cell but not working.
function onEdit2(e) {
//var ss = SpreadsheetApp.getActiveSpreadsheet();
var ss = e.source;
//var s = SpreadsheetApp.openById("1yAJY3gO46A7Wr_fYtVHAB_wSElUdG2kkiH1clRg9o8k").getSheetByName('Name1');
var s = ss.getActiveSheet();
var r = e.source.getActiveRange();
if(s.getName() == "Name1" && r.getColumn() == 1 && r.getValue() == "ok") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Name2");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
the error I'm getting is
TypeError: Can not call method "getActiveSheet" from undefined. (Row 135).
I edited those first lines to those
var ss = SpreadsheetApp.getActiveSpreadsheet();
// var ss = e.source;
//var s = SpreadsheetApp.openById("1yAJY3gO46A7Wr_fYtVHAB_wSElUdG2kkiH1clRg8o9k").getSheetByName('Lista');
var s = ss.getActiveSheet();
var r = e.source.getActiveRange(); // I get error now here can't call getactiverange from undefined .

At this line:
var targetSheet = s.getSheetByName("Name2");
You're running the getSheetByName() on the Sheet and it needs to run on the Spreadsheet to be able to get the other Sheet Name2 , so just change that line to:
var targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Name2");
Also rename your function from onEdit2() to the reserved function name onEdit() so it gets triggered, or create an Installable Trigger
Your function should look like this:
function onEdit(e) {
var ss = e.source;
var s = ss.getActiveSheet();
var r = e.source.getActiveRange();
if(s.getName() == "Name1" && r.getColumn() == 1 && r.getValue() == "ok") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Name2"); // Changed
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
I created an example Spreadsheet here.

When a sheet is edited, the function onEdit() is called, not onEdit2(). onEdit2 seems to be your custom function, so you must be calling that yourself from somewhere else. (maybe from within onEdit()?). If so, are you passing the event object e while calling it? (You have to call it like this:
onEdit2(e);
If you're not passing the parameter e, then you will get the error you're seeing, since ss will be undefined.
ref: GAS-trigger-events

Related

Trying to Clear Columns based on time to trigger onEdit script automatically with an ArrayFormula in place

So I am trying to get my onEdit script to run automatically as rows are added to my Google Spreadsheet. I already have the onEdit script working, and I have an arrayFormula set to add to new rows when added, but this isn't enough to trigger the onEdit. I can clear the contents of the column and that will trigger it, but I need to set a daily clearColumn function based on those rows marked "TRUE" and everything I try just keeps giving me an null/undefined.
**Here is my onEdit script: **
function onEdit(event) {
// assumes source data in sheet named Initial SS Addition
// target sheet of move to named Google to Mailshake
// getColumn with check-boxes is currently set to column 9 or H
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Initial SS Addition" && r.getColumn() == 9 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Google to Mailshake");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
} else if(s.getName() == "Google to Mailshake" && r.getColumn() == 9 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Initial SS Addition");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
**Here is my arrayFormula: **
=ArrayFormula(IF(ROW(H:H)=1,"Appt Done",IF(ISBLANK(H:H),"",TODAY()>=datevalue(H:H))))
**And this is my currenty clearColumn script that is giving me issues: **
function clean0() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var where = ss.getSheetByName('Initial SS Addition');
var triggerCell = where.getRange('I:I').getValue();
if (triggerCell == 'FALSE'){} else // If the cell is true do nothing
if (triggerCell == 'TRUE'){ // If the cell is false run the script
sheet.getRangeList(range).clearContent();
}
}
Any help you can offer would be greatly appreciated! TIA
Managed to figure it out:
Set up a time trigger as follows:
function createTimeTrigger() {
// Creates a trigger to run the moveRows function every hour
ScriptApp.newTrigger('moveRows')
.timeBased()
.everyMinutes(5)
.create();
}
The removed the onEdit function and changed it to just a moveRows function:
function moveRows() {
// assumes source data in sheet named Initial SS Addition
// target sheet of move to named Google to Mailshake
// getColumn with check-boxes is currently set to column 9 or H
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Initial SS Addition");
if (!s) {
return;
}
var columnI = s.getRange("I:I"); // gets the range of cells in column I
var values = columnI.getValues(); // gets the values in the range
for (var i = 0; i < values.length; i++) {
var value = values[i][0];
if (value == true) {
var row = i + 1; // row index is 1-based
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Google to Mailshake");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
}
Now it works perfectly. Thanks to everyone for the ideas :)

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)

Remove a row from a sheet and copy to another spreadsheet

I have managed to remove a row and place in a sheet within the same Google spreadsheet. However when I modify the script to copy a row onto a different sheet, nothing happens:
function onEdit(event) {
var ss =SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "CONTRACT REGISTRY DOCUMENT" && r.getColumn() == 58 && r.getValue() == "X") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var destination = SpreadsheetApp.openById('...');
var targetSheet = destination.getSheetByName("NOT RENEWED");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
The moveTo method can only move data within the same spreadsheet. It is best practice to use range.getValues() and range.setValues() to achieve the same behavior in different spreadsheets.
function onEdit(event) {
var ss =SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "CONTRACT REGISTRY DOCUMENT" && r.getColumn() == 58 && r.getValue() == "X") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var data = r.getValues();
// please supply the destination file ID as parameter here
var destination = SpreadsheetApp.openById('...');
var targetSheet = destination.getSheetByName("NOT RENEWED");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
target.setValues(data);
s.deleteRow(row);
}
}
It seems the problem here is that you're trying to access another file from your trigger (onEdit), but that is not possible because it'd require permission to change another spreadsheet: https://developers.google.com/apps-script/guides/triggers#restrictions
According to a related question, an installable trigger is the way to go here.
In this case, you need to add something like this to your code and run it to create the trigger:
function createSpreadsheetOnEditTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger('moveRowToAnotherSheet')
.forSpreadsheet(ss)
.onEdit()
.create();
}
Based on this trigger, it is necessary to make a few changes to the original code you posted:
function moveRowToAnotherSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getActiveSheet(); // Changed
var r = s.getActiveRange(); // Changed
if(s.getName() == "CONTRACT REGISTRY DOCUMENT" && r.getColumn() == 58 && r.getValue() == "X") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var destination = SpreadsheetApp.openById('...');
var targetSheet = destination.getSheetByName("NOT RENEWED");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1, 1, targetSheet.getLastColumn()); // Changed
target.setValues(s.getRange(row, 1, 1, numColumns).getValues()); // Added to use setValues instead of moveTo
s.deleteRow(row);
}
}

Move a row between different spreadsheets - Google Spreadsheet

I'm a beginner in coding and on SO, but I'm trying to understand what I'm doing and what is happening in the code.
I'm wanting to move a row between different spreadsheets.
I have a script in "CORE" Spreadsheet, which moves a row between the "Home" and "Finished" sheets Link to the spreadsheet:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (s.getName() == "Home" && r.getColumn() == 5 && r.getValue() == true) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Finished");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
else if (s.getName() == "Finished" && r.getColumn() == 5 && r.getValue() == false) {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Home");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
I searched how to move the data located on "Finished" sheet to another spreedsheet called "DATA BASE" Link to the spreadsheet:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Finished");
var range = sheet.getRange("A1:E2");
var values = range.getValues();
var allvals = [];
for (var i = 0; i < values.length; i++) {
allvals.push(values[i]) ;
}
var dataLength = allvals.length;
// alert data
var ui = SpreadsheetApp.getUi();
// ui.alert( JSON.stringify(allvals) )
// copy to another Google Spreadsheet
var newSheet = SpreadsheetApp.openById('1Xn-hrPPr3tQwWMbKdWxHTXcazOqWu1bdHT6A5LZmlD8').getSheets()[0];
var tmp = "A1:E" + dataLength;
var newRange = newSheet.getRange(tmp);
newRange.setValues(values);
}
But I want to transfer the data from sheet "CORE"/"Finished" to sheet "DATA BASE"/ "DB" without rewriting the other rows already on the DB sheet. My idea is to make the spreadsheet "DATA BASE" a real database, where other sheets put data in it and other sheets use this data.
Is it possible to move rows between different spreadsheets like in the first code? I know its impossible to use the .openById() with the function onEdit(), but the most important thing is to move the rows without rewriting the other rows already in the target sheet (DB).
Moving a row to another spreadsheet with installable onEdit trigger
This is just an example of moving the data in a row from one spreadsheet to another with an installable onEdit Trigger. If you wish to play with it don't forget to add the target spreadsheet id.
function onMyEdit(e) {
//e.source.toast('Entry');
var sh=e.range.getSheet();
//Logger.log(JSON.stringify(e));
if(sh.getName()=='Sheet2' && e.range.columnStart==11 && e.value=="TRUE") {
//e.source.toast('Access');
e.range.setValue('FALSE');
var tss=SpreadsheetApp.openById('SSID');
var tsh=tss.getSheetByName('Sheet2');
var v=sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()-1).getValues();
Logger.log(v);
tsh.getRange(tsh.getLastRow()+1,1,v.length,v[0].length).setValues(v);
sh.deleteRow(e.range.rowStart);
}
}

Automatically Copy Rows to Another Sheet Based on Cell Value

I'm pretty new to scripts so I apologize for my potential errors in explaining my issue. I'm working on a spreadsheet that will copy a row to another sheet when it meets a certain criteria (or a certain value in a column) and a second function which will move the row to another sheet upon meeting a certain criteria.
Using related questions/answers, I was able to write a script that deletes a row upon meeting criteria "Outbound" in column 4, see myFunction1 below. For myFunction2, I'm trying to instead just copy the row to another sheet when it meets criteria "M" in column 15, but when I enter that value in column 15 it copies the wrong row information.
Hopefully that makes sense! Code below:
function onEdit(event) {
myFunction1(event);
myFunction2(event);
}
function myFunction1(event){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Trailers in Yard" && r.getColumn() == 4 && r.getValue() == "Outbound") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Outbound");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
function myFunction2(event){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if(s.getName() == "Trailers in Yard" && r.getColumn() == 15 && r.getValue() == "M") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Moves");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).copyTo(target);
}
}
Appreciate the assistance!
Try it this way:
function onEdit(e) {
//myFunction1(e);
myFunction2(e);
}
function myFunction2(e){
//e.source.toast('Flag1');
var sh=e.range.getSheet();
if(sh.getName()=="Sheet2" && e.range.columnStart==15 && e.range.getValue()=="M") {
//e.source.toast('Flag2');
var targetSheet=e.source.getSheetByName("Sheet1");
var target=targetSheet.getRange(targetSheet.getLastRow()+1,1);
sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).copyTo(target);
}
}
You'll have to change the sheet names.