Nesting IF statement inside a loop throwing error - google-apps-script

The error I am receiving:
Exception: The parameters (String,number) don't match the method signature for SpreadsheetApp.Spreadsheet.getRange.
function onOpen() {
var ui = SpreadsheetApp.getUi();
var VALUE = "Hide";
var COLUMN_NUMBER = 11;
ui.createMenu('Hidden Rows')
.addItem('Hide Rows w/Status = Hidden', 'menuItem1')
.addSeparator()
.addItem('Unhide Rows w/Status = Hidden', 'menuItem2')
.addToUi();
}
function menuItem1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var cell = ss.getActiveCell()
var cellValue = cell.getValue();
for (r=1; r<lastRow; r++) {
ss.getRange(r,11);
if(cellValue == VALUE){
activeSheet.hideRow(cell);
};
}
}
function menuItem2() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.alert('Second menu item!');
}

Try this:
var VALUE = "Hide";//global
function menuItem1() {
var ss = SpreadsheetApp.getActive();
var activeSheet = ss.getActiveSheet();
var cell = ss.getActiveCell()
var cellValue = cell.getValue();
for (let r=1;r<lastRow;r++) {
if(cellValue==VALUE){
activeSheet.hideRow(cell.getRow());//this hides the row of the activeCell() not the row of the iteration index
}
}
}
These two values are not global scope in your script:
var VALUE = "Hide";
var COLUMN_NUMBER = 11;
They cannot get hoisted into global from function scope.
Interestingly enough that very line that caused the error does nothing.
ss.getRange(r,11);
You might have r defined to be a string some where so I declared r to have section scope in the loop. You should probably review const,var and let in a JavaScript reference.
It's not clear to me from your script what you had it mind but perhaps this is it.
function runOne() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getActiveSheet();
const rg=sh.getDataRange();
const vs=rg.getValues();
const cell=ss.getActiveCell()
const cellValue=cell.getValue();
vs.forEach(function(r,i){
if(cellValue==r[10]){
sh.hideRows(i+1);
}
});
}

Related

SpreadsheetApp.getActiveSpreadSheet suddenly stops working

At first I had the error of my rows being out of bounds? Then I get this error with "TypeError: SpreadsheetApp.getActiveSpreadSheet is not a function" after I tampered a bit.
I'm not sure why my script isn't working. I have one function to just autoresize all my rows and another function to resize my rows a specific amount (this one keeps saying my rows are out of bounds) Both of these functions use to work for my rows, so I'm not sure what changed.
function onOpen() {
SpreadsheetApp.getUi().createMenu('Scripts')
.addItem('Hide columns', 'hideCols')
.addItem('Show Columns', 'show')
.addItem('Auto Resize Rows', 'autoResizeRows')
.addItem('Resize Rows', 'resizeRows')
.addToUi()
}
function hideCols() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var cells = sheet.createTextFinder("Pictures").matchEntireCell(true).findAll();
cells.map(x => sheet.hideColumns(x.getColumn()));
}
function show() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var cells = sheet.createTextFinder("Pictures").matchEntireCell(true).findAll();
cells.map(x => sheet.showColumns(x.getColumn()));
}
function autoResizeRows() {
var ss = SpreadsheetApp.getActiveSpreadSheet();
var dataRange = ss.getDataRange();
var lastRow = dataRange.getLastRow();
ss.autoResizeRows(2, lastRow);
}
function resizeRows() {
var sss = SpreadsheetApp.getActiveSpreadsheet();
var cellss = sss.getSheetByName('Sheet1');
var responseData = cellss.getDataRange().getValues();
cellss.setRowHeights(2,responseData.length, 300);
}
Fixed:
function onOpen() {
SpreadsheetApp.getUi().createMenu('Scripts')
.addItem('Hide columns', 'hideCols')
.addItem('Show Columns', 'show')
.addItem('Auto Resize Rows', 'autoResizeRows')
.addItem('Resize Rows', 'resizeRows')
.addToUi()
}
function hideCols() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var cells = sheet.createTextFinder("Pictures").matchEntireCell(true).findAll();
cells.map(x => sheet.hideColumns(x.getColumn()));
}
function show() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var cells = sheet.createTextFinder("Pictures").matchEntireCell(true).findAll();
cells.map(x => sheet.showColumns(x.getColumn()));
}
function autoResizeRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ssname = ss.getActiveSheet()
var lastRow = ssname.getDataRange().getLastRow();
ssname.autoResizeRows(2, lastRow-2);
}
function resizeRows() {
var sss = SpreadsheetApp.getActiveSpreadsheet();
var cellss = sss.getSheetByName('Sheet1');
var responseData = cellss.getDataRange().getValues();
cellss.setRowHeights(2,responseData.length-2, 300);
}
Because you've a typo in this function:-
function autoResizeRows() {
var ss = SpreadsheetApp.getActiveSpreadSheet();
var ssname = ss.getActiveSheet()
var lastRow = ssname.getLastRow();
ssname.autoResizeRows(1, lastRow);
}
It's getActiveSpreadsheet not getActiveSpreadSheet that's why your code is breaking, change that S to s.
Reference:-
getActiveSpreadsheet

getLastRow() affecting other cells

Hello I am currently working on a time tracking system. With the following code I track the time how long a value was in a cell. This time is recorded in another worksheet and this is done continuously by appendRow ().
function onEdit(e) {
addTimestamp(e);
}
function addTimestamp(e) {
var ui = SpreadsheetApp.getUi();
var ws = "Tabellenblatt2";
var ss = e.source;
var targetSheet = ss.getSheetByName("Tabellenblatt1");
var range = targetSheet.getRange(3, 2, 1000, 1);
var currentDate = new Date();
var scriptProperties = PropertiesService.getScriptProperties();
if (e.source.getActiveSheet().getName() === ws) {
var cell = ss.getActiveCell();
var val = cell.getValue();
var sourceRowIndex = cell.getRow();
if (val != "") {
let rowToAdd = [val, "", currentDate, ""]
targetSheet.appendRow(rowToAdd);
scriptProperties.setProperty(sourceRowIndex, targetSheet.getLastRow());
} else {
var rowIndex = Number(scriptProperties.getProperty(sourceRowIndex));
if (rowIndex) targetSheet.getRange(rowIndex, 4).setValue(currentDate);
}
}
}
Now one Picture to show my Problem:
The problem is that the cells should start in row 1, is that possible with getLastRow ()?
Determine the last row with content based on another column (e.g. column A):
function onEdit(e) {
addTimestamp(e);
}
function addTimestamp(e) {
var ui = SpreadsheetApp.getUi();
var ws = "Tabellenblatt2";
var ss = e.source;
var targetSheet = ss.getSheetByName("Tabellenblatt1");
var range = targetSheet.getRange(3, 2, 1000, 1);
var currentDate = new Date();
var scriptProperties = PropertiesService.getScriptProperties();
if (e.source.getActiveSheet().getName() === ws) {
var cell = ss.getActiveCell();
var val = cell.getValue();
var sourceRowIndex = cell.getRow();
if (val != "") {
let rowToAdd = [val, "", currentDate, ""]
let rowA=targetSheet.getRange("A1:A").getValues().filter(String).length+1; // new code
targetSheet.getRange(rowA,1,1,rowToAdd.length).setValues([rowToAdd]); // new code
scriptProperties.setProperty(sourceRowIndex, targetSheet.getLastRow());
} else {
var rowIndex = Number(scriptProperties.getProperty(sourceRowIndex));
if (rowIndex) targetSheet.getRange(rowIndex, 4).setValue(currentDate);
}
}
}
it would be easier to change the formula for Time to not display anything at all unless there was an entry, then getLastRow() will work just fine. For help with that, share the formula that's calculating the time.

Installable trigger created using "ScriptApp.newTrigger" has to be re-saved before it will run

I have an Expenses sheet that I copy to the Google Drive folder for each of my relevant users. Each copy of the sheet needs an installable trigger that calls a function to insert additional rows when the last row of data gets edited. These are triggered using the onEdit event. The installable triggers work fine when created manually (via "Edit Current Project's triggers").
To simplify the process of setting up new users, I have scripted the creation of my trigger. Although the script creates the trigger and it appears exactly the same as the manually created one, it only works if I manually open up the trigger, re-select the function to trigger and re-save it.
I can confirm I am the owner when running the creation script.
The behaviour I'm seeing suggests to me that there is something incorrect with the function name in my script however it all looks fine to me. I'd really appreciate some help with this....
function createInsertRowsTrigger(){
Logger.log('Id='+ss.getId());
createInstallableTrigger("onEditOfLastRow",ss.getId());
}
function createInstallableTrigger(funcName,ssId) {
if(!isTrigger(funcName)) {
ScriptApp.newTrigger(funcName).forSpreadsheet(ssId).onEdit().create();
}
}
function isTrigger(funcName){
Logger.log('In isTrigger');
var r=false;
if(funcName){
Logger.log('Function found');
var allTriggers=ScriptApp.getProjectTriggers();
for(var i=0;i<allTriggers.length;i++){
if(funcName==allTriggers[i].getHandlerFunction()){
r=true;
Logger.log('trigger already exists');
break;
}
}
}
return r;
}
The full code is here....
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('SCLGA Expenses Menu')
.addItem('Approve Expenses', 'ApproveExpenses')
.addToUi();
resetValidationRules();
}
//===========================================================================================
// global
var ss = SpreadsheetApp.getActive();
//===========================================================================================
function onEditofLastRow(e) {
var value = ss.getActiveSheet().getRange(3, 6).getValue();// row number of the last but one row
editedCol =e.range.getSheet().getActiveCell().getColumn();
editedRow =e.range.getSheet().getActiveCell().getRow();
// if the last cell in the last row is edited...create some more rows...
if(editedCol==7 && editedRow== value-1){
showAlert('Looks like you need some more rows... ');
insertRows();
}
}
function createInsertRowsTrigger(){
Logger.log('Id='+ss.getId());
createInstallableTrigger("onEditOfLastRow",ss.getId());
}
function createInstallableTrigger(funcName,ssId) {
if(!isTrigger(funcName)) {
ScriptApp.newTrigger(funcName).forSpreadsheet(ssId).onEdit().create();
}
}
function isTrigger(funcName){
Logger.log('In isTrigger');
var r=false;
if(funcName){
Logger.log('Function found');
var allTriggers=ScriptApp.getProjectTriggers();
for(var i=0;i<allTriggers.length;i++){
if(funcName==allTriggers[i].getHandlerFunction()){
r=true;
Logger.log('trigger already exists');
break;
}
}
}
return r;
}
function showAlert(msg) {
var ui = SpreadsheetApp.getUi();
var result = ui.alert(msg);
}
function insertRows() {
// this function inserts some new rows and copies relevant formulas and formats
// this value tells us where the next data section starts
var value = ss.getActiveSheet().getRange(3, 6).getValue();
var rowsToAdd = 5;
var firstRow = value-rowsToAdd;
var sh = ss.getActiveSheet();
var lCol = sh.getLastColumn();
var range = sh.getRange(firstRow, 1, rowsToAdd, lCol);
// copy formulas
var formulaRange1 = sh.getRange(firstRow, 1, rowsToAdd, 1);
var formulaRange2 = sh.getRange(firstRow, 8, rowsToAdd, lCol-8);
var formulas1 = formulaRange1.getFormulasR1C1();
var formulas2 = formulaRange2.getFormulasR1C1();
// insert rows
sh.insertRowsAfter(firstRow+rowsToAdd-1, rowsToAdd);
// define new range
newRange1 = sh.getRange(firstRow+rowsToAdd, 1, rowsToAdd, 1);
newRange2 = sh.getRange(firstRow+rowsToAdd, 8, rowsToAdd, lCol-8);
// set formulas
newRange1.setFormulasR1C1(formulas1);
newRange2.setFormulasR1C1(formulas2);
// copy formatting for range 2
range.copyFormatToRange(sh, 1, lCol-8, firstRow+rowsToAdd, firstRow+rowsToAdd+rowsToAdd-1);
resetValidationRules();
resetTransactionUploadFormulas();
}
function resetTransactionUploadFormulas(){
var sheet = ss.getSheetByName('Transactions to load');
sourceFormulas = sheet.getRange(2,1,1,12).getFormulasR1C1();
for (i=3; i<=250; i++)
newRange=sheet.getRange(i,1,1,12).setFormulasR1C1(sourceFormulas);
}
function resetValidationRules(){
var value = ss.getActiveSheet().getRange(3, 6).getValue();
var firstRow = 5;
var sh = ss.getActiveSheet();
var lCol = sh.getLastColumn();
var range = sh.getRange(firstRow, 1, 245, lCol);
// Apply validation rules to all rows
for(i = 1; i <= 250; i++){
currentRowNumber = 4+i;
var cell = SpreadsheetApp.getActive().getRange('F'+currentRowNumber);
var eventRange = sh.getRange("L"+currentRowNumber+":BB"+currentRowNumber)
var rule = SpreadsheetApp.newDataValidation().requireValueInRange(eventRange).build();
if (value != currentRowNumber && value+1 != currentRowNumber)
cell.setDataValidation(rule);
}
}

Appending multiple rows from a source sheet to a destination sheet in Google Sheets

I am using code from this older thread to copy a range of cells from a source sheet and paste them to the last row of a destination sheet.
https://support.google.com/docs/forum/AAAABuH1jm04B0WxqiEJns/?hl=en&gpf=%23!topic%2Fdocs%2F4B0WxqiEJns
The suggested code copies and pastes the data on the same sheet so I attempted (and failed) to modify it:
function appendEagleData() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName("Eagle New Rows");
var dest = ss.getSheetByName("Eagle Static Data")
var source = sh.getRange("A4:J20");
var v = source.getValues();
dest.getRange(dest.getLastRow() + 1, 1, v.length, v[0].length).setValues(v);
}
...Clearly, I'm a little out of my depth. Any help would be appreciated.
function appendEagleData() {
var ss=SpreadsheetApp.getActive();
var sh1=ss.getSheetByName("Eagle New Rows");
var rg1=sh1.getRange(4,1,sh1.getLastRow()-3,10);
var sh2=ss.getSheetByName("Eagle Static Data")
var rg2=sh2.getRange(sh2.getLastRow()+1,1);
rg1.copyTo(rg2);
}
try this:
function appendEagleData() {
var ss=SpreadsheetApp.getActive();
var sh1=ss.getSheetByName("Eagle New Rows");
var rg1=sh1.getRange(4,1,getColumnHeight(2,sh1,ss)-3,10);
var sh2=ss.getSheetByName("Eagle Static Data")
var rg2=sh2.getRange(sh2.getLastRow()+1,1);
rg1.copyTo(rg2);
}
function getColumnHeight(col,sh,ss){
var ss=ss || SpreadsheetApp.getActive();
var sh=sh || ss.getActiveSheet();
var col=col || sh.getActiveCell().getColumn();
var rg=sh.getRange(1,col,sh.getLastRow(),1);
var vA=rg.getValues();
while(vA[vA.length-1][0].length==0){
vA.splice(vA.length-1,1);
}
return vA.length;
}

Google Script: When cell is filled, have prompt ask if user wants to run script

I have written a script to clean up and move data between 3 different sheets. A user first paste a data extract on to the "Extract" page, and then runs the script.
When a user paste the data into cell A1 on the "Extract" page, I would like a prompt box to ask the user if they would like to run the script; if Yes, run script, if No, don't run script and show message. How would I go about doing this?
This is what I have so far...everything after the first function works.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Extract");
if(ss.s().getRange("A1").getValue() != ""){
var ui = SpreadsheetApp.getUi()
var response = ui.alert('Would you jbot to find new claims for you?', ui.ButtonSet.OK_CANCEL);
if (response == ui.Button.OK) {
jbot();
} else {
Logger.log('The user clicked "No" or the close button in the dialog\'s title bar.');
}
}
}
function jbot(){
movetobot();
deleteRows();
removeDupesInOtherSheets();
deleteCol();
cleanup();
movetoqueue();
message();
};
function movetobot() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Extract");
var ts = ss.getSheetByName("bot");
s.getRange("A1:BW").moveTo(ts.getRange("A1"));
}
function deleteRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("bot");
var r = s.getRange("BO:BO");
var v = r.getValues();
for(var i=v.length-1;i>=0;i--)
if(v[0,i]=='#POSTLESSEE' || v[0,i]=='#TDI CRC_OANKURA' || v[0,i]=='#Partpaymentoffer' || v[0,i]=='#TDI_CRC_DVANKURA' || v[0,i]=='#partpaymentdupe' )
s.deleteRow(i+1);
}
function removeDupesInOtherSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName("bot").getDataRange().getValues();
var s2 = ss.getSheetByName("Queue").getDataRange().getValues();
// iterate 'Queue' and check in 'bot' if duplicate values exist
var nS1 = [];
var s2Col1 = [];// data in column1 of Queue
for(var n in s2){
s2Col1.push(s2[n][0]);
}
for(var n in s1){ // iterate '180418970' and test col 1 vs col 1 in 'Queue'
var noDup1 = checkForDup(s1[n],s2Col1)
if(noDup1){nS1.push(noDup1)};// if not present in 'Queue' then keep
}
Logger.log(nS1);// view result
ss.getSheetByName("bot").getDataRange().clear();// clear and update sheets
ss.getSheetByName("bot").getRange(1,1,nS1.length,nS1[0].length).setValues(nS1);
}
function checkForDup(item,s){
Logger.log(s+' = '+item[0]+' ?')
if(s.indexOf(item[0])>-1){
return null;
}
return item;
}
function deleteCol() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var lastCol = sheet.getLastColumn();
var keep = [1,2,3,4,45,53,74, 75]; // array of column numbers to keep
for (var col=lastCol; col > 0; col--) {
if (keep.indexOf(col) == -1) {
// This isn't a keeper, delete it
sheet.deleteColumn(col);
}
}
}
function cleanup() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
sheet.getRange("B1:B").moveTo(sheet.getRange("H1"));
sheet.deleteColumn(2)
sheet.deleteRow(1)
var cell = sheet.getRange("D:D");
cell.setNumberFormat("m/d/yy");
var cell = sheet.getRange("F:F");
cell.setNumberFormat("m/d/yy");
var cell = sheet.getRange("A:A");
cell.setHorizontalAlignment("center");
var cell = sheet.getRange("C:D");
cell.setHorizontalAlignment("center");
var cell = sheet.getRange("F:G");
cell.setHorizontalAlignment("center");
sheet.autoResizeColumn(2)
sheet.autoResizeColumn(5)
sheet.autoResizeColumn(7)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var cell = sheet.getRange("BW1");
cell.setFormula("=COUNT(A:A)");
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var range = sheet.getRange("A1:G");
range.sort({column: 4, ascending: true})
}
function movetoqueue() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
// skip row 1 (header) and beyond column G
var range = sheet.getRange(1,1,sheet.getLastRow()-1,7);
sheet = spread.getSheetByName("Queue");
var rows = sheet.getRange(1,1,sheet.getLastRow(),1).getValues();
// search for first blank row column 1
for( var i=0; i<rows.length; i++ ) {
if( rows[i][0] === "" ) {
var offset = sheet.getRange(1,1).offset(i,0);
range.copyTo(offset);
break;
}
}
}
function message() {
SpreadsheetApp.getActive().getSheetByName("Queue").activate();
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var range = sheet.getRange("bot!BW1:BW1");
var data = range.getValue();
Browser.msgBox(data + " new claims have been added to the queue. Thank you for using jBot!");
}
Your onEdit(e) will trigger the alert regardless of which cell is edited. You need to check the event range to limit it to cell A1 of Extract like this.
function onEdit(e) {
if( e.range.getSheet().getName() === "Extract" ) {
if( e.range.getA1Notation() === "A1" ) {
if( e.value !== "" ) {
var ui = SpreadsheetApp.getUi();
// Do the rest of your stuff here
}
}
}
}