insertRowsBefore() Method causing error: cannot convert (range) to class - google-apps-script

I was trying to write a script in google spreadsheets that, will read a range from a defined cell, take its value and Insert as many rows as the range would indicate, and then copy and paste an specific range also given by a range value in a cell.
Apparently the copy and paste range value works, but the range value for the insertRowsBefore is unable to convert the range value, any idea why this happens? I get this error
cannot convert (range) to class
here is how the scripts looks like:
function CopyActualvsWMS() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("ActualVsSystem");
var value0 = sheet.getRange('T4');
var r1 = value0.getValue();
var insert =ss.getSheetByName("DataBase").insertRowBefore(r1);
var value1 = sheet.getRange('T3');
var cr1 = value1.getValue();
var source = ss.getRange(cr1);
source.copyTo(ss.getRange("DataBase!a2"), {contentsOnly: true});
}

The problem is coming from this line:
var insert =ss.getSheetByName("DataBase").insertRowBefore(r1);
You are putting a variable name r1 into the parameter, but the parameter must be a number (integer), not a string or a range reference. The variable r1 doesn't evaluate to an integer. It's probably a string.
Google Documentation - insertRowBefore()

Related

Selecting Disjoint Range of Data with Variable Last Row Using GetRangeList Apps Script

I have a sheet sheetUnitsDB with a bunch of data. I want to select the data from specific columns and paste it onto another sheet sheetRentRoll. I could do this by selecting each entire column specified and feeding it into getRangeList, but for efficiency, I'd like to only include the rows that have data. There are two ways I see of doing this using getRangeList:
Option 1: Use getRangeList with r1c1 Notation
The developer page claims getRangeList can take a1notation or r1c1 notation. Does anyone know how to feed r1c1 notation into getRangeList? In my example below, the LastUnitRow is 10 so I am attempting to select the range [C5:C10]:
var app = SpreadsheetApp;
var activeSheet = app.getActiveSpreadsheet(); //Get current active spreadsheet
var sheetRentRoll = activeSheet.getSheetByName('Rent Roll');
var sheetUnitsDB = activeSheet.getSheetByName('UnitsDB');
var LastUnitRow = sheetUnitsDB.getLastRow(); //Last row of RentRoll DB with data, 10 in this example
var testrange = sheetUnitsDB.getRangeList([5,3,LastUnitRow-4,1]); //should select range C5:C10 but yields error
Logger.log(testrange)
This returns the error: "Exception: Range not found". I know my notation is wrong but don't know how to fix it.
Option 2: Convert r1c1 to a1 and Use getRangeList with a1 Notation
If it is somehow erroneous that getRangeList can be used with r1c1 notation, alternatively I have a code in the example below that takes the r1c1 notation above for the range [C5:C10] and returns "C5:C10". I convert this to a string which returns "['C5:C10'] and attempt to pass this to getRangeList which also returns an error:
var app = SpreadsheetApp;
var activeSheet = app.getActiveSpreadsheet(); //Get current active spreadsheet
var sheetRentRoll = activeSheet.getSheetByName('Rent Roll');
var sheetUnitsDB = activeSheet.getSheetByName('UnitsDB');
var LastUnitRow = sheetUnitsDB.getLastRow(); //Last row of RentRoll DB with data, 10 in this example
var rangeR1 = sheetRentRoll.getRange(5,3,LastUnitRow-4,1); //selects range C5:C10
var rangeA1 = rangeR1.getA1Notation(); //returns "C5:C10" (without quotation marks)
rangeA1 = "['" + rangeA1 + "']";
Logger.log(rangeA1); //returns ['C5:C10']
var testrange = sheetUnitsDB.getRangeList(rangeA1); //should select range C5:C10 but yields error
Logger.log(testrange)
which gives the error: "Exception: The parameters (String) don't match the method signature for SpreadsheetApp.Sheet.getRangeList."
What am I doing wrong?
Go to the documentation search on getRangeList() look at tutorial

Copying from Spreadsheet to another Spreadsheet error

I am a total beginner using appscript, can someone please help me to resolve this error.
The parameters (String) don't match the method signature for SpreadsheetApp.Range.setValues
function Input1() {
var sss = SpreadsheetApp.openById('10xap9qOf487MB9M9FQ-Turp81X_ZIoDVMyFY-Puf9BU');
var ss = sss.getSheetByName('Input'); // ss = source sheet
var values = ss.getRange("A2:H2").getValue();
var tss = SpreadsheetApp.openById('1thJ5uqhfwZhdxsE0B9MhyhjwcFZpe4A0Ty3erGIuWpU');
var ts = tss.getSheetByName('Entries'); // ts = target sheet
ts.getRange(ts.getLastRow()+1,1,1,8).setValues(values);
}
You are trying to take the values in the Range A2:H2 on Sheet "Input", and copy them to the row following the last row on Sheet="Entries".
The problem is in this line of code:
var values = ss.getRange("A2:H2").getValue();
Instead of using getValue(), you should use getValues()
Your range is 8 columns wide:
getValue() "returns the value of the top-left cell in the range". In this case it returns the value of a single cell=A2.
getValues() will return "the rectangular grid of values for [the] range". This is just what you want so that you can use it with the setValues() method in the last line of the script.

How can I avoid a VLOOKUP Error that occurs when I delete a name?

The pictures used are only from an example sheet! My basic problem is that I have a list called Assignment in which names appear (dropdown list). For Location (in the assignment sheet) I use the following formula: =IF(C2<>"",VLOOKUP(C2,'Input Data'!C$3:D$7,2,FALSE),"")
These names are assigned certain values, they are in the same line. The names are defined in a worksheet called Input Data!
If I now delete a name like Green, John from the Input Data worksheet, then I get the following error in another worksheet (Evaluation). (More than 40 people have access to this worksheet and randomly delete names)In this evaluation worksheet the values are evaluated by the following formula:
=ARRAY_CONSTRAIN(ARRAYFORMULA(SUM(IF((IF($B$2="dontcare",1,REGEXMATCH(Assignment!$E$3:$E$577,$B$2 &"*")))*(IF($B$3="dontcare",1,(Assignment!$E$3:$E$577=$B$3)))*(IF($B$4="dontcare",1,(Assignment!$D$3:$D$577=$B$4)))*(IF($B$5="dontcare",1,(Assignment!$F$3:$F$577=$B$5)))*(IF($B$6="dontcare",1,(Assignment!$B$3:$B$577=$B$6))),(Assignment!S$3:S$577)))), 1, 1)
The following error appears in the evaluation sheet:
Error:
During the evaluation of VLOOKUP the value "Green, John" was not found.
How can I avoid this error? Is it possible to avoid this error with a macro that deletes Names from assignment sheet that are not in the Input data sheet? Do you have any ideas for a code?Maybe a Formula or perhaps a Macro?
example sheet with explanation: https://docs.google.com/spreadsheets/d/1OU_95Lhf6p0ju2TLlz8xmTegHpzTYu4DW0_X57mObBc/edit#gid=1763280488
If what you want to do is make sure that rows are deleted in a sheet when there are incorrect values you could try something like this in Apps Script:
function onEdit(e) {
var spreadsheet = e.source;
var assignment = spreadsheet.getSheetByName("Assignment");
var assignmentRange = assignment.getDataRange();
var assignmentNames = assignment.getRange(3, 2, assignmentRange.getNumRows());
var inputData = spreadsheet.getSheetByName("Input Data");
var inputDataRange = inputData.getDataRange();
var i = 1;
while(assignmentNames.getNumRows() > i){
var currentCell = assignmentNames.getCell(i, 1);
var txtFinder = inputDataRange.createTextFinder(currentCell.getValue());
txtFinder.matchEntireCell(true);
if(!txtFinder.findNext()){
assignment.deleteRow(currentCell.getRow())
}else{
// We are only steping when no elements have been deleted
// Otherwise we would skip rows due to shifting in row deletion
i++;
}
}
}
Explanation
onEdit is a special function name in Apps Script that would execute every time it's parent sheet is modified.
After that we retrieve the spreadsheet from the event object
var spreadsheet = e.source;
Now we get the relevant range in the Assignment sheet. Look at the usage of getDataRange documentation to avoid retrieving unnecessary cell values. And from that range we actually get the specific column we are interested on.
var assignment = spreadsheet.getSheetByName("Assignment");
var assignmentRange = assignment.getDataRange();
var assignmentNames = assignment.getRange(3, 2, assignmentRange.getNumRows());
Now we do the same for the other sheet(Input Data):
var inputData = spreadsheet.getSheetByName("Input Data");
var inputDataRange = inputData.getDataRange();
Note: Here I'm not getting a specified column because I assume that the full name will not repeat in any other column. But if you want you could get the specified range as I have done at Assignment.
After that we want to look for specific values in the Assignment range that don't exist in the Input Data sheet, you should try the TextFinder.
For every name in Assignment you should create a TextFinder. I have also forced to make a whole cell match.
var i = 1;
while(assignmentNames.getNumRows() > i){
var currentCell = assignmentNames.getCell(i, 1);
var txtFinder = inputDataRange.createTextFinder(currentCell.getValue());
txtFinder.matchEntireCell(true);
If txtFinder finds a value the findNext() will evaluate to true. In the other hand when the txtFinder does not find a value it will be null and evaluated to false.
if(!txtFinder.findNext()){
assignment.deleteRow(currentCell.getRow())
}else{
// We are only stepping forward when no elements have been deleted
// Otherwise we would skip rows due to shifting in row deletion
i++;
}
}
}

Random string generator randomizing too often

I'm looking for input on a small random string generator project.
I'm trying to create a random string generator that puts three words together, where I can then save strings that I like to another sheet.
I'm using a basic script to assign a RANDBETWEEN formula to 3 specific cells, which works great to generate the strings, but it keeps recalculating with each additional step in the script it seems. I'd like to run one function then if I like the string I would run another function to store the string. However, when I try that it has already recalculated the RANDBETWEEN formulas and it saves something completely different.
I have an example sheet here:
https://docs.google.com/spreadsheets/d/1TWziyjjLQJJApkHCqrLzNGMFU0sf-vNEOOSatuhHURo/edit?usp=sharing
And here is the code I'm using for the "Go" and "Save" buttons, respectively:
function generateString() {
var ss = SpreadsheetApp.openById('1b9rP39sgZDOZqu7AmZhOxX9J8CMukmUw7NPY3Qzuq78');
var sheet = ss.getSheetByName('Randomizer');
var cell = sheet.getRange('D4');
var cell2 = sheet.getRange('E4');
var cell3 = sheet.getRange('F4');
cell.setValue('=INDEX(A:A,RANDBETWEEN(1,counta(A:A)))');
cell2.setValue('=INDEX(A:A,RANDBETWEEN(1,counta(A:A)))');
cell3.setValue('=INDEX(A:A,RANDBETWEEN(1,counta(A:A)))');
var cell4 = sheet.getRange('P4');
cell4.copyTo (sheet.getRange ('P5'), {contentsOnly: true}); //an attempt to paste values to record the random string
}
function saveString() {
var ss = SpreadsheetApp.openById('1b9rP39sgZDOZqu7AmZhOxX9J8CMukmUw7NPY3Qzuq78');
var sheet = ss.getSheetByName('Randomizer'); //replace with source Sheet tab name
var range = sheet.getRange('P4'); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('1b9rP39sgZDOZqu7AmZhOxX9J8CMukmUw7NPY3Qzuq78');
var tsheet = tss.getSheetByName('Saved Strings'); //replace with destination Sheet tab name
tsheet.getRange(tsheet.getLastRow()+1, 1, 1, 1).setValues(data);
}
Please let me know if anyone has some ideas on how to make this work properly. Thanks!
RANDBETWEEN the same as RAND are volatile functions. That means that their results changes every time that spreadsheet is recalculated.
If you need to keep the randomized to result be "freezed" for a while instead of this functions one alternative to consider is the use of a custom function as they are recalculated only when at least one of its arguments changes.
Related
Refresh data retrieved by a custom function in Google Sheet

When using setFormulas I get error Cannot find function error "object function getFontColor() {/* */}."

I'm trying to create a script that copies down formula the length of the sheet (stitched together on the back of other SO posts I found while researching):
var originRange = ss.getSheetByName('data_prep').getRange('C6:I6');
var formulas = originRange.getFormulas();
var target = ss.getSheetByName('data_prep').getRange('C7:I');
for(i in target) {
target[i].setFormulas(formulas);
}
When I run this function I get:
TypeError: Cannot find function setFormulas in object function getFontColor() {/* */}.Dismiss
What I had hoped/expected was for all the formulas in C6:I6 to be copied into each row starting C7 down the length of the sheet.
The function works for one row at a time. So if I set target as just C7:I7 and get rid of the for loop it works.
Why am I getting this getFont error?
How can I get my script to copy the formulas in C6:I6 down the entire sheet?
As an alternative to 2, how can I get my script to copy down as far as while there is data in column A?
Maybe try something like this:
var ss= SpreadsheetApp.getActiveSpreadsheet();
var dataPrepSheet = ss.getSheetByName('data_prep')
var originRange = dataPrepSheet.getRange('C6:I6');
var everyRow = dataPrepSheet.getMaxRows().toString();
var target = dataPrepSheet.getRange('C7:I' + everyRow);
originRange.copyTo(target);
SpreadsheetApp.flush();
Use the getMaxRows() method to get every every row in the spreadsheet, whether it's got content or not. That returns an integer, so convert it to a string then use a text formula to create the A1 notation.
Then, don't set the formulas, use copyTo()