google sheet custom function to multiply columns - google-apps-script

I am working on a google app script to fetch a range, multiply one column in the range by another column in the range, then output to a different column within the original range. This should be simple, but I can't figure it out.
function myFunction() {
var sheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var data = sheet.getRange("A1:B22").getValues();
var newData = []
for (i in data){
var row = data[i];
var multiply = row[0] * row[1]
newData.push(multiply)
}
sheet.getRange(1,3,22,1).setValues(newData)
}

Thanks for the recommendation, but that didn't work unfortunately. The reason I'm not using the arrayformula function is because this is actually a small piece of a larger, more complicated function.
What did end up working is pushing the "multiply" variable into newData as an array by putting it in brackets.
function myFunction() {
var sheet = SpreadsheetApp.getActive().getSheetByName("Sheet1");
var data = sheet.getRange("A1:B22").getValues();
var newData = []
for (i in data){
var row = data[i];
var multiply = row[0] * row[1]
newData.push([multiply])
Logger.log(newData)
}
sheet.getRange(1,3,22,1).setValues(newData)
}

Related

Combine Multiple Sheets to One Dynamic Master [duplicate]

How can I merge multiple tabs in a Google Spreadsheet using Google App Script ? Data in all the tabs keep changing.
For example, I have 'Sheet1', 'Sheet2' and 'Sheet3' in a Google spreadsheet. Data in all these sheets have 3 columns - Name and email ID & Region. Now, I want to merge/combine the data present in these 3 sheets/tabs into a 4th Sheet i.e. 'Sheet 4' having same Columns (name, email Id & Region). The 4th sheet should have data as - data of Sheet1 followed by Sheet2 and then Sheet3. The number of rows in all the 3 sheets keeps changing.
=query({Sheet1!A1:C; Sheet2!A1:C; Sheet3!A1:C}, "where Col1 is not null", 0)
I wouldn't use a script for this; the worksheet formulas are much faster, at least most of the time.
Make sure you use semicolons to separate the ranges. Semicolons are the End_Of_Row operator for array literals.
If you really want to use a script...
function combineSheets() {
var sApp = SpreadsheetApp.getActiveSpreadsheet();
var s1= sApp.getSheetByName("Sheet1");
var s2= sApp.getSheetByName("Sheet2");
var s3= sApp.getSheetByName("Sheet3");
var s4= sApp.getSheetByName("Sheet4");
// If Sheet4 doesn't exist you'll need to create it here.
var s1values = s1.getRange(1,1,s1.getLastRow(),3).getValues();
var s2values = s2.getRange(1,1,s2.getLastRow(),3).getValues();
var s3values = s3.getRange(1,1,s3.getLastRow(),3).getValues();
// Now, we can put out all together and stuff it in Sheet4
var s4values = [];
s4values = s1values.concat(s2values,s3values);
s4.getRange(1,1,s4values.length,3).setValues(s4values);
}
You don't need a script for this. In the fourth sheet, enter the following formula in A2:
={filter(Sheet1!A2:C, len(Sheet1!A2:A)); filter(Sheet2!A2:C, len(Sheet2!A2:A)); filter(Sheet3!A2:C, len(Sheet3!A2:A))}
It returns the contents of columns A-C where the entry in column A is nonempty, and stacks them in one array.
You can use Google Apps Scripts for this.
var ss = SpreadsheetApp.getActiveSpreadsheet();
function TotalsSheet() {
var totaldata = [];
var sheets = ss.getSheets();
var totalSheets = 2;
for (var i=0; i < totalSheets; i++) {
var sheet = sheets[i];
var range = sheet.getDataRange();
var values = range.getValues();
for (var row in values) {
totaldata.push(values[row]);
}
}
return totaldata;
}
function Start() {
var All = ss.insertSheet("All-Values");
var totaldata = TotalsSheet();
for (var i = 0; i < totaldata.length; i++) {
All.appendRow(totaldata[i]);
}
}
//This Script is must faster
function consolidateData(){
// defined all variables
var sheetNames = [];
var dataSheet = [];
var dataValues = [];
var conso=[];
var header = [["Name","email ID","Region"]];
var ws = SpreadsheetApp.getActiveSpreadsheet();
// get all sheets
var allsheets = ws.getSheets();
for(var s in allsheets){
var sheet = allsheets[s];
sheetNames[s] = sheet.getName();
dataSheet[s] = ws.getSheetByName(sheetNames[s]);
// adding all sheet's data to a single variable
conso = conso.concat(dataSheet[s].getRange("A2:C"+dataSheet[s].getLastRow()).getValues());
}
// writing data into new sheet
var newSheet = ws.insertSheet().setName("Consolidated_Data");
newSheet.getRange("A1:C1").setValues(header);
newSheet.getRange("A2:C"+(conso.length+1)).setValues(conso);
}
I made one that will do nine tabs' consolidation, with more rows and columns.
=filter({{Sheet1!A1:Q500};{Sheet2!A1:Q500};{Sheet3!A1:Q500};{Sheet4!A1:Q500};{Sheet5!A1:Q500};{Sheet6!A1:Q500};{Sheet7!A1:Q500};{Sheet8!A1:Q500};{Sheet9!A1:Q500}},{{Sheet1!A1:A500};{Sheet2!A1:A500};{Sheet3!A1:A500};{Sheet4!A1:A500};{Sheet5!A1:A500};{Sheet6!A1:A500};{Sheet7!A1:A500};{Sheet8!A1:A500};{Sheet9!A1:A500}}<>"")
I'm wondering if it is a way to generalize the initial filter formula so that you can cut and paste in more sheet numbers, so for instance if there were 20 or 30 tabs with 25 columns, could you consolidate that easily into one page?

Filter column on multiple criteria and copy to different sheet

I want to move filtered data from one sheet to a different sheet.
I can do this for a single filtered value ex: Money but I want to filter on multiple values from an array ex: ["Money", "Society", "Impacts"]
I can not figure out how to loop through the filterValues array and collect all the values from the different filterValues.
I just get the filtered values of rawData for the last value in filterValues
I can do this a different way but I am trying to get a better understanding of filtering
function myFunction() {
var filterValues = ["Money", "Society"]; //filter values.
var col = 5; // column "E".
var sheetName = "Elements";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sht = ss.getSheetByName(sheetName);
var rng = sht.getDataRange();
var rawData = rng.getDisplayValues();
var out = rawData.filter(dataFilter);
function dataFilter(arr) {
return arr[col-1]== filterValues;
}
const osh=SpreadsheetApp.getActive().getSheetByName("A");
osh.clear();
osh.getRange(1,1,out.length,out[0].length).setValues(out);
};
tried this
for (var i = 0; i <= filterValues.length-1; i++) {
var out = rawData.filter(dataFilter);
function dataFilter(arr) {
return arr[col-1]== filterValues[i];
}
}
You can use array.includes() to check if the current row column e value is listed in your filterValues for your array filter function.
Sample code:
function myFunction() {
var filterValues = ["Money", "Society"]; //filter values.
var col = 5; // column "E".
var sheetName = "Elements";
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sht = ss.getSheetByName(sheetName);
var rng = sht.getDataRange();
var rawData = rng.getDisplayValues();
var out = rawData.filter(dataFilter);
function dataFilter(arr) {
return filterValues.includes(arr[col-1]);
}
Logger.log(out);
const osh=SpreadsheetApp.getActive().getSheetByName("A");
osh.clear();
osh.getRange(1,1,out.length,out[0].length).setValues(out);
};
What it does?
Get the data range values
Filter the 2-d array values if column E value was found in your filterValues array.
Write the filtered array on the destination sheet.
Output:
Source Sheet: Elements
Destination Sheet: A
You can just use a basic filter function combined with array syntax like you'd use in SumProduct. Example: =filter(List!A:A,(List!A:A="Society")+(List!A:A="Money")).
I don't think you'd need to use Google App Scripts. See this spreadsheet

Google App Scripts Merging Data from multiple Sheets [duplicate]

How can I merge multiple tabs in a Google Spreadsheet using Google App Script ? Data in all the tabs keep changing.
For example, I have 'Sheet1', 'Sheet2' and 'Sheet3' in a Google spreadsheet. Data in all these sheets have 3 columns - Name and email ID & Region. Now, I want to merge/combine the data present in these 3 sheets/tabs into a 4th Sheet i.e. 'Sheet 4' having same Columns (name, email Id & Region). The 4th sheet should have data as - data of Sheet1 followed by Sheet2 and then Sheet3. The number of rows in all the 3 sheets keeps changing.
=query({Sheet1!A1:C; Sheet2!A1:C; Sheet3!A1:C}, "where Col1 is not null", 0)
I wouldn't use a script for this; the worksheet formulas are much faster, at least most of the time.
Make sure you use semicolons to separate the ranges. Semicolons are the End_Of_Row operator for array literals.
If you really want to use a script...
function combineSheets() {
var sApp = SpreadsheetApp.getActiveSpreadsheet();
var s1= sApp.getSheetByName("Sheet1");
var s2= sApp.getSheetByName("Sheet2");
var s3= sApp.getSheetByName("Sheet3");
var s4= sApp.getSheetByName("Sheet4");
// If Sheet4 doesn't exist you'll need to create it here.
var s1values = s1.getRange(1,1,s1.getLastRow(),3).getValues();
var s2values = s2.getRange(1,1,s2.getLastRow(),3).getValues();
var s3values = s3.getRange(1,1,s3.getLastRow(),3).getValues();
// Now, we can put out all together and stuff it in Sheet4
var s4values = [];
s4values = s1values.concat(s2values,s3values);
s4.getRange(1,1,s4values.length,3).setValues(s4values);
}
You don't need a script for this. In the fourth sheet, enter the following formula in A2:
={filter(Sheet1!A2:C, len(Sheet1!A2:A)); filter(Sheet2!A2:C, len(Sheet2!A2:A)); filter(Sheet3!A2:C, len(Sheet3!A2:A))}
It returns the contents of columns A-C where the entry in column A is nonempty, and stacks them in one array.
You can use Google Apps Scripts for this.
var ss = SpreadsheetApp.getActiveSpreadsheet();
function TotalsSheet() {
var totaldata = [];
var sheets = ss.getSheets();
var totalSheets = 2;
for (var i=0; i < totalSheets; i++) {
var sheet = sheets[i];
var range = sheet.getDataRange();
var values = range.getValues();
for (var row in values) {
totaldata.push(values[row]);
}
}
return totaldata;
}
function Start() {
var All = ss.insertSheet("All-Values");
var totaldata = TotalsSheet();
for (var i = 0; i < totaldata.length; i++) {
All.appendRow(totaldata[i]);
}
}
//This Script is must faster
function consolidateData(){
// defined all variables
var sheetNames = [];
var dataSheet = [];
var dataValues = [];
var conso=[];
var header = [["Name","email ID","Region"]];
var ws = SpreadsheetApp.getActiveSpreadsheet();
// get all sheets
var allsheets = ws.getSheets();
for(var s in allsheets){
var sheet = allsheets[s];
sheetNames[s] = sheet.getName();
dataSheet[s] = ws.getSheetByName(sheetNames[s]);
// adding all sheet's data to a single variable
conso = conso.concat(dataSheet[s].getRange("A2:C"+dataSheet[s].getLastRow()).getValues());
}
// writing data into new sheet
var newSheet = ws.insertSheet().setName("Consolidated_Data");
newSheet.getRange("A1:C1").setValues(header);
newSheet.getRange("A2:C"+(conso.length+1)).setValues(conso);
}
I made one that will do nine tabs' consolidation, with more rows and columns.
=filter({{Sheet1!A1:Q500};{Sheet2!A1:Q500};{Sheet3!A1:Q500};{Sheet4!A1:Q500};{Sheet5!A1:Q500};{Sheet6!A1:Q500};{Sheet7!A1:Q500};{Sheet8!A1:Q500};{Sheet9!A1:Q500}},{{Sheet1!A1:A500};{Sheet2!A1:A500};{Sheet3!A1:A500};{Sheet4!A1:A500};{Sheet5!A1:A500};{Sheet6!A1:A500};{Sheet7!A1:A500};{Sheet8!A1:A500};{Sheet9!A1:A500}}<>"")
I'm wondering if it is a way to generalize the initial filter formula so that you can cut and paste in more sheet numbers, so for instance if there were 20 or 30 tabs with 25 columns, could you consolidate that easily into one page?

Google scripts - issue with string vs cell as function parameter

I'm learning Google script as I go along and came across an issue that I could not find a solution for.
I have a function that takes in several several strings and one cell as params.
I assume passing a cell is not same as passing its value (string too btw)
Please find attached code:
//return id assigned to data(cell) sheetname
function findInColumn(column, data, colName, sheetname) {
/*
data = cell (cell value is 'bag_backpack.png') does not work
var range = SpreadsheetApp.getActiveRange();
var col = range.getColumn();
var row = range.getRow();
var range2 = SpreadsheetApp.getActiveSheet().getRange(row,col+1);
data = range2.getValue(); (cell value is 'bag_backpack.png') <---fail too
data = 'bag_backpack.png'; <---works
*/
var sheet = SpreadsheetApp.getActive().getSheetByName(sheetname);
var column = sheet.getRange(column + ":" + column); // like A:A
var values = [];
for (var index = 0; index < column.getValues().length; index++) {
values.push(column.getValues()[index][0])
}
var colIndex = getByName(colName, sheetname);
var rowIndex = values.indexOf(data);
//grab id value of data
var range = sheet.getRange(rowIndex+1,colIndex+1);
var data = range.getValue();
return data
}
While I value and need your feedback I kindly request your bear in mind I'm a novice at best and I've spend several hours searching before asking here.
Thank you for your help.
Edit: bag_backpack.png is the content of a cell I'm searching in a column to get the row number of said cell.
var rowIndex = values.indexOf(data);
Returns the index I need.
However... if I feed a cell to the function instead of a string like a cell elsewhere with bag_backpack.png as its content or even derive said value from it:
var range = SpreadsheetApp.getActiveRange();
var col = range.getColumn();
var row = range.getRow();
var range2 = SpreadsheetApp.getActiveSheet().getRange(row,col+1);
data = range2.getValue(); (cell value is 'bag_backpack.png') <---fail too
In said case:
var rowIndex = values.indexOf(data);
gives out -1 instead of index desired.
Most of what you have doesn't make sense to me. I'm guessing that this is what you want. Since I can't figure out what you want, perhaps you can tell me what I missed.
function findInColumn(column,sheetname) {
var sh=SpreadsheetApp.getActive().getSheetByName(sheetname);
var rg=sh.getRange(column + ":" + column); /
var vA=rg.getValues();
var values = [];
for (var i=0;i<vA.length; i++) {
values.push(vA[i][0]);
}
return values
}
I want to thank everyone for taking the time to reply.
the issue was NOT with the code but with some of the first filename having uppercase in the id,name sheet while the binder sheet it did not.(at least 5 hours on Tent.png/tent.png)
I'm attaching a link to my finished work in hopes it benefits anyone.
https://docs.google.com/spreadsheets/d/1jCy1I4r6PeY3kUWrhNno2XO18Jghq6_b1kyN3AflidM/edit?usp=sharing

Google Script insert formula in 1 column where cell are black

Hi could someone help me with this script im trying to insert a formula in all the blank cell from (J15) to (J38) here is what ive got but I just cant seem to get it the proper way any help would be greatly appreciated.
function test() {
var ssA = SpreadsheetApp.getActive(); //changed from openById() for my convenience
var ss = ssA.getActiveSheet(); //change from getSheetByName() for my convenience
var range = ss.getRange(15,10,24,1); //row 2 column 7 (G) lastRow 1 column
var data = range.getValues(); //Gets all data
for(var i=0;i<data.length;i++) //this runs over entire selected range
{
if(!data[i][0]) //If true then it's blank
{
data[i](('=Iferror(If(G15="",, if($B$5 = Iferror(query(\'Client
List\'!$A$2:$A, "select A where A =\'"&$B$5&"\'"),""),VLOOKUP($B$5,Client_Rate,2,False),VLOOKUP(D15,Config_Rate_List
,2,False))),"")');)
}
}
range.setFormula(data); //Sets all data.
}
You want to put the formula to "J15:J38". If my understanding is correct, how about this modification?
I thought that it is possible that the cells of "J15:J38" have the values and formulas. So in this modified script, the formula is put to the empty cells which don't have both. The flow of script is as follows.
Retrieve values and formulas from "J15:J38".
Create range list.
Put the formula using setFormula().
I think that there are several solutions for your situation. So please think of this as one of them.
Modified script :
function test() {
var ssA = SpreadsheetApp.getActive(); //changed from openById() for my convenience
var ss = ssA.getActiveSheet(); //change from getSheetByName() for my convenience
var range = ss.getRange(15,10,24,1); //row 2 column 7 (G) lastRow 1 column
var data = range.getValues(); //Gets all data
// The following script was modified.
var formulas = range.getFormulas();
var rangeList = [];
var offset = 15;
for(var i=0;i<data.length;i++) {
if(!data[i][0] && !formulas[i][0]) {
rangeList.push("J" + (offset + i));
}
}
var formula = '=Iferror(If(G15="",, if($B$5 = Iferror(query(\'Client List\'!$A$2:$A, "select A where A =\'"&$B$5&"\'"),""),VLOOKUP($B$5,Client_Rate,2,False),VLOOKUP(D15,Config_Rate_List,2,False))),"")';
ss.getRangeList(rangeList).setFormula(formula);
}
Note :
I was not sure whether the sheet name is Client List or ClientList, because of the line break in your script.
I'm not sure about the formula which was put to cells.
About your title, "black" of "Google Script insert formula in 1 column where cell are black" is "blank"?
Reference :
getRangeList(a1Notations)
If this was not what you want, I'm sorry.
Edit :
Unfortunately, the formulas in an array cannot be put the cells using the range list yet. I think that Sheets API can put various formulas once. But as a simple way, here, I would like to propose the following script.
function test() {
var ssA = SpreadsheetApp.getActive(); //changed from openById() for my convenience
var ss = ssA.getActiveSheet(); //change from getSheetByName() for my convenience
var range = ss.getRange(15,10,24,1); //row 2 column 7 (G) lastRow 1 column
var data = range.getValues(); //Gets all data
// The following script was modified.
var formulas = range.getFormulas();
var val = [];
var offset = 15;
for(var i=0;i<data.length;i++) {
if(!data[i][0] && !formulas[i][0]) {
ss.getRange("J" + (offset + i)).setFormula('=Iferror(If(G' + (offset + i) + '="",, if($B$5 = Iferror(query(\'Client List\'!$A$2:$A, "select A where A =\'"&$B$5&"\'"),""),VLOOKUP($B$5,Client_Rate,2,False),VLOOKUP(D' + (offset + i) + ',Config_Rate_List,2,False))),"")');
}
}
}