getRange outputting "Range" instead of values - google-apps-script

So, I'm making a code that copies certain data from our EOD worksheet, and copy/pasting the data onto another sheet, which acts as a summary.
I've got most of the code already working, but running into trouble with the getRange output. It just shows "Range" in the cell instead of my input, which should all be numbers.
function myFunction() {
var source = [];
var destSheet = SpreadsheetApp.getActive().getSheetByName('SnapshotSpreadsheet');
var destRange = destSheet.getRange(destSheet.getLastRow()+1,2);
source.push(sheet.getRange('B20'));
source.push(sheet.getRange('E20:F20'));
source.push(sheet.getRange('H20'));
source.push(sheet.getRange ('J20:I20'));
source.push(sheet.getRange ('M18'));
source.push(sheet.getRange ('K20'));
source.push(insertDate());
destSheet.getRange(2,1,1,7).setValues([source]);
I've included just the portion that is causing the issue. I defined source as an array, and stored values into the array, then just called for them to be output on the next available line. Everything seems to be lining up alright, just the values are all "Range".

You need to use getValue() (if single cell) or getValues() (if multiple cells) to get the content of those ranges.
Cfr https://developers.google.com/apps-script/reference/spreadsheet/range#getValue()

You'll need to do .getValues() for it to return the values of the cells
var values = sheet.getRange('E20:F20').getValues();
This returns a Two Dimensional array of values, so you'll have to work around that in your code. For example the line of code I just wrote would be an array like
[[Value at E20, Value at F20]]
so in order to access the Value at E20, you would call values[0][0] or for Value at F20, - values[0][1]

Related

Data into rows and colums

I'm relatively new to this, I've written a function in Google Apps Script, getting data from an API.
The problem is that it's inserted into one single cell, instead of multiple rows and columns.
Can anybody help?
Tried googling examples
What I do
function spotpriser() {
var priser = 'api.energidataservice.dk/dataset/Elspotprices' + '?start=2022-07-01&end=2022-07-02' + '&sort=HourDK';
var response = UrlFetchApp.fetch(priser);
Logger.log(response);
var fact = response.getContentText();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1,1).setValue([fact]);
}
if you do getRange(1,1).setValue() it is normal that all the data get inserted into one cell only: the one define by the range (aka A1).
Instead what you probably want to do is to get a larger range, corresponding the dimensions of your retrieved data.
For example, let's say you retrieved 3 lines of data, and one line of data is supposed to be displayed on 2 columns.
You first need to create an array of size 5 (nb of rows) where each element will also be an array, of size 2 (nb of cols for each element).
let myArray = [
[elt1_col1_value, elt1_col2_value],
[elt2_col1_value, elt2_col2_value],
[elt3_col1_value, elt3_col2_value]
]
Then you can insert this array into the right number of cells, i.e defining the right range
sheet.getRange(1,1,myArray.length,myArray[0].length).setValues(myArray); // start at row 1, col 1, insert the right number of rows and cols based on the array
Note that I use setValues (with the s) to indicate that it writes in several cells.
Also make sure there is at least one element in myArray otherwise myArray[0].length will throw an error.
Documentation for getRange.

Trying to append rows what am I not grasping?

Summary:
I need to get a range of values from one sheet, then set them into the first empty row of the second sheet. If that row is full, then append to the next.
I can get the script to set values into their corresponding cells, but not append; and I've been able to append a single cell value into an empty cell, but not the entire range. What am I not comprehending?
The goal:
Basically I'm taking user input (lets say race data) and saving it to another sheet for referencing later. (possibly to average race times by weight and height or something)
Research: I'm a bit new to this, but I've also done a good bit of research, such as ben collins free introductory course and other questions from here (just to name a couple):
[Get Range] SpreadsheetApp: getRange and setValues
[Copy Range] How to copy row ranges in Google docs?
Code
Grab my data:
const data1 = sheet1.getRange("A2:F2").getValues(); //grab data
Sets the range where I want it, but doesn't append:
sheet2.getRange("A2:F2").setValues(data1) //gets range and sets the value
So I've tried:
function r () {sheet2.getRange(newRow,1,1,data1.length).setValues(data1)};
return (r);
and even added:
sheet2.appendRow(data1);
(newRow is essentially getLastRow)
The above gives me a row of set values, then appends this in the following row: [Ljava.lang.Object;#f2a6014
-which in my research I've found what it is, but I don't understand why it happens.
I know I'm overlooking something or arranging something incorrectly but I cant figure out what it is that I'm not understanding.
Using your first two example I wrote this script and it works:
function copydata() {
const ss=SpreadsheetApp.getActive();
const sheet1=ss.getSheetByName('Sheet1');
const sheet2=ss.getSheetByName('Sheet2');
const data1 = sheet1.getRange("A2:F2").getValues();
sheet2.getRange("A2:F2").setValues(data1);
}
And this works also assuming that you realize that data1 is only a single row but it's still a two dimensional array so you have to use data1[0] to extract the single dimensional array from the two dimensional array
function copydatatofrom() {
const ss=SpreadsheetApp.getActive();
const sheet1=ss.getSheetByName('Sheet1');
const sheet2=ss.getSheetByName('Sheet2');
const data1 = sheet1.getRange("A2:F2").getValues();
sheet2.getRange("A2:F2").setValues(data1);
sheet2.appendRow(data1[0]);
}

google sheets script get cell contents

I have a list of URLs in a google spreadhseet and I want to get the cell reference to be used as a URL in the script.
An example of a URL I will be getting data from: https://politicsandwar.com/api/nation/id=31831
I want to do something like getValue.("O2") or var urlData = "O2" but I don't know how to go about getting to that point.
You should first get a range and then get its values.
var sheet = SpreadsheetApp.getActiveSheet();
//Gets all cell values form column "O" starting from row 2. Returns a 2d array
var wholeColumnUrls = SpreadsheetApp.getActiveSheet().getRange("O2:O").getValues();
//Gets value from specific cell "O2".
var singleCellUrl = SpreadsheetApp.getActiveSheet().getRange("O2").getValue();
There are multiple ways of defining a range, in this example we use the A1notation variant. Which seems to be what you're looking for.
Also, notice the difference between getValues() and getValue(). The first returns a 2d array like:
[
[https://politicsandwar.com/api/nation/id=31831]
,[https://politicsandwar.com/api/nation/id=31832]
,[https://politicsandwar.com/api/nation/id=31833]
]
while the latter returns a single value like https://politicsandwar.com/api/nation/id=31831
That way you can choose wether you get all the values and iterate over them, or have your own logic to determine each cell and get the values separately.

setFormulas to a new spreadsheets when created

I have been searching through question and example everywhere but I can not seem to find an answer. I need to set these formulas in the header row and columns AQ:1 to AV:1(AQ1:AV1).
["={"Hours:";ArrayFormula((IF(LEN(AE2:AE),((AF2:AF-AE2:AE)*24)+(((T2:T-S2:S)*24))+(((I2:I-H2:H)*24)),)))}",
"={"Rest Hours:";ArrayFormula((IF(LEN(AE2:AE),((M2:M)*24)+(((X2:X)*24))+(((AJ2:AJ)*24)),)))}",
"={"Rest Hours Wages:";ArrayFormula((IF(LEN(AE2:AE),(AI2:AI*(AJ2:AJ*24)+(L2:L*(M2:M*24)+(W2:W*(X2:X*24)))),)))}",
"={"Hours-RestHours:";ArrayFormula((IF(LEN(AE2:AE),((AQ2:AQ-AR2:AR)),)))}",
"={"Rate:";ArrayFormula((IF(LEN(AE2:AE),((E2:E+P2:P+AB2:AB)),)))}"],
and I need to put this into the second row of column AQ (AQ2).
["=ArrayFormula((IF(LEN(AE2:AE),((AT2:AT*AU2:AU)+AS2:AS),)))}"],
I keep getting this error message and I cannot save the script.
Missing ] after element list. (line 138, file "Code")
I think I know why but I need the headers to be titled with the correct text because I use the headers in other functions.
function setFormulas(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// This sets the formulas to be a row of sums, followed by a row of averages right below.
// The size of the two-dimensional array must match the size of the range.
var formulas = [
["={"Hours:";ArrayFormula((IF(LEN(AE2:AE),((AF2:AF-AE2:AE)*24)+(((T2:T-S2:S)*24))+(((I2:I-H2:H)*24)),)))}",
"={"Rest Hours:";ArrayFormula((IF(LEN(AE2:AE),((M2:M)*24)+(((X2:X)*24))+(((AJ2:AJ)*24)),)))}",
"={"Rest Hours Wages:";ArrayFormula((IF(LEN(AE2:AE),(AI2:AI*(AJ2:AJ*24)+(L2:L*(M2:M*24)+(W2:W*(X2:X*24)))),)))}",
"={"Hours-RestHours:";ArrayFormula((IF(LEN(AE2:AE),((AQ2:AQ-AR2:AR)),)))}",
"={"Rate:";ArrayFormula((IF(LEN(AE2:AE),((E2:E+P2:P+AB2:AB)),)))}",
"={"Wages:";ArrayFormula((IF(LEN(AE2:AE),((AT2:AT*AU2:AU)+AS2:AS),)))}"],
["=ArrayFormula((IF(LEN(AE2:AE),((AT2:AT*AU2:AU)+AS2:AS),)))}"],
];
var cell = sheet.getRange("AQ1:AW2");
cell.setFormulas(formulas);
}
Am I missing something or am I doing it completely wrong and need to find another way to do it. I also need to add the formulas to every sheet in the spreadsheet but I have not been able to test if it works. Thank you in advance for any help.
UPD:
It seems like double quotes are interfering here. To avoid this, you can use single quotes for formula enclosure and double quotes within formula, like this:
'={"Hours:";ArrayFormula((IF(LEN(AE2:AE),((AF2:AF-AE2:AE)*24)+(((T2:T-S2:S)*24))+(((I2:I-H2:H)*24)),)))}'
As mentioned in comments:
Arrays would expand so you are likely to need setting formulas in one row, like AQ1:AW1
Besides, if there's source data in columns AQ:AU (by the looks of formulas), setting array formulas in the same columns will most likely return error: Array result was not expanded because it would overwrite data in AQ18.
You seem to have an extra } at the end of the last formula
Try this and adjust to your needs:
function setFormulas(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// This sets the formulas to be a row of sums, followed by a row of averages right below.
// The size of the two-dimensional array must match the size of the range.
var formulas = [
['={"Hours:";ArrayFormula((IF(LEN(AE2:AE),((AF2:AF-AE2:AE)*24)+(((T2:T-S2:S)*24))+(((I2:I-H2:H)*24)),)))}',
'={"Rest Hours:";ArrayFormula((IF(LEN(AE2:AE),((M2:M)*24)+(((X2:X)*24))+(((AJ2:AJ)*24)),)))}',
'={"Rest Hours Wages:";ArrayFormula((IF(LEN(AE2:AE),(AI2:AI*(AJ2:AJ*24)+(L2:L*(M2:M*24)+(W2:W*(X2:X*24)))),)))}',
'={"Hours-RestHours:";ArrayFormula((IF(LEN(AE2:AE),((AQ2:AQ-AR2:AR)),)))}',
'={"Rate:";ArrayFormula((IF(LEN(AE2:AE),((E2:E+P2:P+AB2:AB)),)))}',
'={"Wages:";ArrayFormula((IF(LEN(AE2:AE),((AT2:AT*AU2:AU)+AS2:AS),)))}',
'=ArrayFormula((IF(LEN(AE2:AE),((AT2:AT*AU2:AU)+AS2:AS),)))']
];
var cell = sheet.getRange("AW1:BC1");
cell.setFormulas(formulas);
}

setFormulas won't skip empty array elements, over-writes values

Consider the code below: it sets values then sets functions across a range, however it overwrites the values that were set.
function test() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange("A1:B2");
var values = [["First","row"],["Second","row"]];
var formulas = [["=42",""],["","=77"]];
range.setValues(values);
range.setFormulas(formulas);
}
Why is it that setting an empty formula will overwrite any set value and vice versa? Wondering if there is a way to skip setting an individual array element. I have tried 'undefined' and 'null with no luck.
Having to get the ranges of specific areas that require formulas for values to prevent overwriting of data adds an extra layer complexity to the script I'm writing.
Thanks for reading!
I think the problem can be largely mitigated by the fact that setValues() can be used to set formulae.
var range = ss.getRange("A1:B2");
var values = range.getValues();
// process the array, eg values[0][0] = "=42";
range.setValues();
This certainly explains why setting values overwrites formulas, but wouldn't it be nicer if there were a way to getValuesandFormulas together into an array?
If (like me) you were distracted into getValues and getFormulas, realise that you can use copyTo between ranges to copy the overall contents!