I want to fetch the range of all cells with data in it, but not including the header row.
I found that getDataRange() captures all the cells with data in it, and to avoid including the first row, I thought I could just delete the first element in what I am assuming is an array?
How can I do this/ is there a more elegant way to approach this problem?
You want to retrieve the values without the 1st row using getDataRange().
If my understanding is correct, how about this sample script? Please think of this as just one of several answers.
Sample script 1 :
In this sample, offset() is used. In this case, before the values are retrieved, the range is modified.
var sheet = SpreadsheetApp.getActiveSheet();
var headerRowNumber = 1;
var values = sheet.getDataRange().offset(headerRowNumber, 0, sheet.getLastRow() - headerRowNumber).getValues();
Logger.log(values)
Sample script 2 :
In this sample, shift() is used. In this case, after the values were retrieved, the values are modified.
var sheet = SpreadsheetApp.getActiveSheet();
var values = sheet.getDataRange().getValues();
values.shift();
Logger.log(values)
References:
offset()
shift()
If I misunderstood your question and this was not the direction you want, I apologize.
If you want the header and the rest of the values separately
var values=SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var header=values.splice(0,1);
Logger.log(values);
Logger.log(header);
Related
I like to modify this script to duplicate a single record as many times as I need into gsheets.
As of now my script below just posts a single record as intended.
Now I like to add a variable(quantity) and have the record posted(append) onto the sheet as many times as the quantity variable says.
function sendProductIDtoQRCodeSheet(fieldData){
var sheet = SpreadsheetApp.openById('1fUNWqzHosafsdafasdfas--B4').getSheetByName('LISTS');
var lRow = sheet.getLastRow();
var range = sheet.getRange("A1:A");
var value1 = fieldData.productId;
var value2 = fieldData.productName;
var joinedValues = value1 + " | " + value2;
sheet.appendRow([
fieldData.productId, joinedValues
]);
}
In order for you to achieve what you want, you can use a for loop and a take a look at these methods since they can be of help:
getRange(row, column, numRows, numColumns) - for getting the range with the given numbers of rows and columns;
setValues(values) - for setting the values on the specified range for which they must match the dimensions of it;
You might also want to search similar questions here on Stack which can be of help.
Is there a reason you can't use a loop?
Check the documentation for the sheet class. There's a method called insertRows(rowIndex, numRows) that could be what you're looking for. It inserts a number of blank rows equal to numRows at the index. You can just populate them after you make them.
I have a function that adds an auto-expanding formula to some Header row cell
In the next line of code, I get the Display Values and then post them back to the sheet
I am concerned that I will be getting the values in the range of the auto-expanding formulas before they have finished expanding
Will this r.getDisplayValues(); get the values before the auto-expansion has finished? thereby getting values with blank data that should have data
I have tested various scenarios, but this is not definitive
Also, I have not been able to find anything in searching on this
Thank you
function setFormulasAE_n() {
var ss =SpreadsheetApp.getActive();
var sheet =ss.getSheetByName('Elements');
var LC = sheet.getLastColumn();
var LR = sheet.getLastRow();
//Auto-expanding Formulas to be added
//Two dim array with 1 row
var formulas = [[
"=ArrayFormula({\"ig_TagsHistorical\";iferror(vlookup(INDIRECT(\"Elements!A2:A\"&counta(Elements!$AJ$1:$AJ)), \'HelperElements_(ignore)\'!$A$2:$G, {5}, 0))})",
"=ArrayFormula({\"Additional Networks\";iferror(vlookup(INDIRECT(\"Elements!A2:A\"&counta(Elements!$AJ$1:$AJ)), \'Helper_(ignore)\'!$A$2:$D, {4}, 0))})",
]];
//Add auto-expanding formulas to Cell(s)
var cell = sheet.getRange(1,LC+1,1,formulas[0].length);
cell.setFormulas(formulas);
//Get range and post back Display Values
var r = sheet.getRange(1,LC+1,LR,formulas[0].length);
var v = r.getDisplayValues();
r.setValues(v)
}
The setFormulas() function you have used in the script is synchronous which essentially means that the code following the instruction won't be executed until the functions finishes the execution.
Therefore, r.getDisplayValues() will always get the values after the auto-expansion.
What you could do to make sure that the values you get are the expected ones is to use the flush() function after the cell.setFormulas(formulas) line of code. What flush() does is basically applying all the pending Spreadsheet changes - more specifically the formulas you need to set.
Furthermore, you can check these links since they might be of help to you:
SpreadsheetApp Class - flush();
Range Class - setFormulas().
Is there any way to select a range specified from within another named range?
For example if I have a named range say "firstRange" and I want to get just the 2nd column from within that range to copy to another named range.
I can do this by copying cells individually with a for loop but it takes a long time.
Unfortunately
getRangeByName("firstRange").getRange(1,1,2) is not valid as getRange is not a method of getRangeByName
Thanks
How about this method? I think that there are several answers for your situation. So please think of this as one of them. The flow is as follows.
Flow:
Range of values you want is retrieved from the source named-range by offset().
When getLastRow() is used to the named range, the returned value is the last row of the named range.
Retrieve the destination named-range.
Copy the retrieved source range to the destination range.
Sample script:
In this sample script, the 2nd column of named range of firstRange is copied to the named range of secondRange.
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Retrieve source range.
var sourceRange = ss.getRangeByName("firstRange");
var src = sourceRange.offset(0, 1, sourceRange.getLastRow(), 1);
// Retrieve destination range.
var destinationRange = ss.getRangeByName("secondRange");
// Copy from source range to destination range.
src.copyTo(destinationRange);
For example, if you want to copy the retrieved source range to 2nd column of the destination range, please modify var destinationRange = ss.getRangeByName("secondRange") as follows.
var destinationRange = ss.getRangeByName("secondRange").offset(0, 1, 1, 1);
References:
getLastRow()
offset()
copyTo()
If this was not what you want, I'm sorry.
You can get the named range and then get the values which returns a multi-dimensional array. Then you can parse the values that you are looking for out of that. For example
var parsed = SpreadsheetApp.getActiveSpreadsheet()
.getRangeByName('namedRange')
.getValues()
.map(function(row) {
return [row[1]];
});
This gets all the values from your named range and then maps over them and grabs the values from the second column (the 1 index in this example)
I hope that helps.
I've been working on this simple code in google scripts to execute on a button.
I want the user to be able to select two cells side by side, then click the button. The 1st selected cell will be updated with the date, the cell to the right will be incremented by one. So far I've gotten this far:
function increment() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var activeValues = activeSheet.getActiveRange().getValues();
var newValues = [[Utilities.formatDate(new Date(), "UTC-8",
"yyyy/MM/dd"),activeValues[1]+1]];
activeValues.setValues(newValues);
}
I think that I need to use setValues on getActiveRange but I'm not sure how to change the active range into an array which can be set by setValues.
I don't think I'm calling the correct element (1st element, second column) with activevalues[1]. Not sure how to call it.
Right now I get error: Cannot find function setValues in object,1.
The error occurs because activeValues is an array of arrays / 2D array but setValues is a method of Class Range.
Assuming that activeValues has the same shape that newValues, to do the minimal changes to your code you could instead of
activeValues.setValues(newValues);
use
activeSheet.getActiveRange().setValues(newValues);
The element from activeValues should be one of these:
Number(activeValues[0][1])
Number(activeValues[1][0])
The choice depends on whether the cells are horizontal or vertical.
And the values are set with activeSheet.getActiveRange().setValues(newValues).
I should start with letting you know that I'm an extreme novice in JS. My background is almost solely in SQL/VBA. So, any tips you could provide would be greatly appreciated, whether it's in coding or in Stack Overflow etiquette.
Problem Background:
I've got a Script that I use for sending outbound e-mails from Google Form responses, hosted within a Google Sheet and set to OnFormResponse(). Typically, I'm only asked to send back specific bits of information from the form responses within a HTML template e-mail. However, the business case I have now is that I need to look up the values from another sheet, where an adjacent column's value matches a form response value. With the value that's matched, I need to set the value of a specific column/row (F:F) within the Form Response sheet with it.
Example:
Here's a simplified version of what the Form Responses sheet looks like, along with the formula that I would typically use:
Here's what the other tab, 'Unique Databases!', looks like:
So, my understanding of JavaScript arrays is that on the Form Responses Sheet, I would load all columns (A:E in this example) into a variable, and get the values. Then, get columns A:B of 'Unique Databases!', which loads those values into another array. If that is accurate, how do you compare the index of 1 array against the index of another, and return an adjacent match?
Thanks!
You can try this function:
function dbmanager(dbname) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Unique Databases!');
var rg=sh.getDataRange();
var vA=rg.getValues();
var r='';
for(var i=0;i<vA.length;i++){
if(dbname==vA[i][0]){
r=vA[i][1];
break;
}
}
return r;
}
I'm not sure you need to use a apps script to make a comparison like this. Perhaps a much faster way would be to use a query in the sheet. Something like this maybe:
=QUERY(Sheet1!A1:B3,"SELECT B WHERE A ='"&E2&"'",0)
The first part of the query is looking up the unique databases data. The second part selects column B in the unique databases data where column A is equal to the data base name in the form responses data. Note this query goes in column F of the responses data.
Another alternative using code might be something like this. with the code below running.
function getFormData(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet2');
var getRange = sheet.getRange('E2:E');
var data = getRange.getValues();
var lookup = getLookupData();
data.forEach(function(item,index){
sheet.getRange(index + 2 , 6).setValue(lookup[item])
})
}
function getLookupData() {
var obj = {};
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1');
var range = sheet.getRange('A2:B6');
var data = range.getValues();
data.forEach(function(item){
obj[item[0]] = item[1];
})
Logger.log(obj)
return obj;
}