Create a function in Google Sheets with these conditions - google-apps-script

I'm using two different sheets, one for the values I'm going to need and one for counting the values of the first Sheet based on a number of conditions.
[Sheet 1]
[Sheet 2]
I'm using this formula to Count the values:
=(COUNTIFS('Sheet 1'!A:A;"*m003*";'Sheet 1'!A:A;"*m001*";'Sheet 1'!A:A;"*P165*";'Sheet 1'!B:B;1))/(COUNTIFS('Sheet 1'!A:A;"*m001*";'Sheet 1'!A:A;"*P165*"))
With this context, I'd like know if it'd be possible to create a function, macro or something that would let me do this operation by inputting some cells with the information I'd need instead of having to write "m003", "m001", "p165" or another value every time I want to execute the formula mentioned with any variation.

Replace them with cells:
=(COUNTIFS('Sheet 1'!A:A;"*"&A1&"*";'Sheet 1'!A:A;"*"&C1&"*";'Sheet 1'!A:A;"*"&D1&"*";'Sheet 1'!B:B;1))/(COUNTIFS('Sheet 1'!A:A;"*"&C1&"*";'Sheet 1'!A:A;"*"&D1&"*"))
where,
A1: m003
C1: m001
D1: P165

Related

I need to clean up and split words from a mess of data into their own cells in a row. How can I accomplish this?

I am attempting to create documentation from an export of data that gives me a jumbled mess all in one cell that I need to clean up and extract certain bits from.
Here is an example:
[{"label":"Native Invoice","value":"native_invoice","displayOrder":0,"hidden":false,"readOnly":false},{"label":"Data Sync","value":"data_sync","displayOrder":1,"hidden":false,"readOnly":false}]
All of this is in one cell, and I need to have only the following information in their own individual rows:
Native Invoice
Data Sync
This example only has 2 values, but some that I am working on have hundreds, and it is taking far too long to manually copy and paste the values I need into their own cells.
Note: I am working in Google Sheets exclusively.
If I'm understanding you correctly, you want to pull anything after "label": without quotes. If that's the case, and if you are open to a formula instead of a script, supposing that your raw-data block were in A1, place this in B1:
=ArrayFormula(IFERROR(QUERY(FLATTEN(REGEXREPLACE(IF(NOT(REGEXMATCH(SPLIT(REGEXREPLACE(A1,"label.:.([^"&CHAR(34)&"]+)","~|$1~"),"~"),"\|")),,SPLIT(REGEXREPLACE(A1,"label.:.([^"&CHAR(34)&"]+)","~|$1~"),"~")),"\|","")),"WHERE Col1 Is Not Null")))
Here is how a custom function can look like:
function parse(txt) {
var jsn = JSON.parse(txt);
return [jsn[0].label, jsn[1].label];
}
Here is how it works:
You put the data into cell A1, put the formula =parse(A1) into the cell B1, and get the results in cells B1 and B2.
Update
If you want to get labels from all objects of the data, here is another variant of the function:
function get_labels(txt) {
return JSON.parse(txt).map(x => x.label); // get 'label' from all the objects
}
It works about the same way:

Google Sheets Join information from two pages with query & vlookup

I know this has been asked several times, but I just can't seem to understand how to write the formula and I'm hoping to get some help.
Consider the following (example data) sheet:
https://docs.google.com/spreadsheets/d/1t_I_stZmZea4sfGPsCu6GtBhGJJT16CZ-sEu7JubFKc/edit?usp=sharing
First, note that I am importing data on "API Data" utilizing importJSON().
My goal is to combine (join) data from two sheets. I need "dataseries cloudcover" from 'API data' and "Dataseries example,Dataseries example 1,Dataseries example 2" from 'join'.
I gave it a shot here:
=query('API data'!A:L,"Select " & vlookup(B:B,'API data'!B:L,3,FALSE) & ",B,C,D,E,F,G,H,I,J,K,L")
Here is a SS of what I would like to see
This formula can help you to get that data:
Note: Just add the formula in A2
={ARRAYFORMULA(IF(ISBLANK('API data'!C2:C),"",ARRAYFORMULA(VLOOKUP('API data'!C2:C,'API data'!C2:D25,2)))),ARRAYFORMULA(IF(ISBLANK(Join!A2:A),"",ARRAYFORMULA(VLOOKUP(Join!A2:A,Join!A2:D25,{2,3,4},FALSE))))}
And it will look like this:
Edit:
Editing and adding more information about the use of this formula.
The formula is constructed with 2 different VLookUps, 1 for each tab, and they are merged using:
={First Array, Second Array}
The first Array is:
ARRAYFORMULA(IF(ISBLANK('API data'!K2:K),"",ARRAYFORMULA(VLOOKUP('API data'!K2:K,'API data'!K2:L25,2))))
The second Array is:
ARRAYFORMULA(IF(ISBLANK(Join!I2:I),"",ARRAYFORMULA(VLOOKUP(Join!I2:I,Join!I2:L25,{2,3,4},FALSE))))
The core part of the first array for this formula is:
ARRAYFORMULA(VLOOKUP('API data'!K2:K,'API data'!K2:L25,2))
The IF(IsBlank(column,"",Vlookup) will remove any empty value of the Array.
The same thing with the second Array, with the difference that I use an Array {2,3,4} to call all the columns in the second sheet.
Reference:
VLOOKUP function.
ARRAYFORMULA function.
IF function.
ISBLANK function.

How to use custom function ExtractAllRegex() as an array formula? [Google Sheets]

I'm using #Wiktor Stribiżew 's custom function ExtractAllRegex(). The script extracts all occurrences of a Regex pattern. In the example, I extract all words in column A starting with "v_"
Here is a Google Sheet showing what I'm trying to do.
The original strings are stored in column A. The custom function/the matches are in column B.
Wictors function works great for single cells. It also works great when I manually drag the formula down the column.
Here's Wictor's original code:
function ExtractAllRegex(input, pattern,groupId,separator) {return Array.from(input.matchAll(new RegExp(pattern,'g')), x=>x[groupId]).join(separator);}
Description:
input - current cell value
pattern - regex pattern
groupId - Capturing group ID you want to extract
separator - text used to join the matched results.
The question is, how do I turn column B into a working array formula? Or, perhaps better, how do I modify Wictor's script so it accepts a range instead and auto-fills down column B?
I updated your script to:
function ExtractAllRegex(input, pattern,groupId,separator) {
return input.map ? input.map( inp => ExtractAllRegex(inp, pattern, groupId, separator)) :
Array.from(input.matchAll(new RegExp(pattern,'g')), x=>x[groupId]).join(separator);
}
and changed the formula in B2 to
=ExtractAllRegex(A2:A13,"(v_.+?\b)",0," ")
See if that works for you?

How to create INDIRECT array string of multiple sheet references in Google Sheets?

I am attempting to use a query to display data off multiple Google Sheets. I make a new sheet every week that has a specific sheet name, e.g. Week of 01/13, Week of 01/06 and so forth.
The following is where my idea spawned from for reference:
I have a summary sheet that is using COUNTA(INDIRECT("'" & A5 &
"'!E4:E",true)
A5 being a cell that concatenates a date and words to replicate the
sheet names.
The row on the summary sheet does not populate until B5<=today()
So I am able to set it an forget it and the sheet will continue to
give me my weekly data as the days progress and keeps the sheets clean
until the week is upon us.
Long story short, I have a query that I use that gives me all the data I need with a specific parameter but I have to manually update the data syntax array with the new sheet names each week.
=QUERY({'Week of 01/13'!A:P;'Week of 01/06'!A:P;'Week of 12/30'!A:P;'Week of 12/23'!A:P;'WEEK OF 12/16'!A:P;'WEEK OF 12/09'!A:P;'WEEK OF 12/02'!A:P;'WEEK OF 11/25'!A:P;'WEEK OF 11/18'!A:P;'WEEK OF 11/11'!A:P;'WEEK OF 11/04'!A:P;'WEEK OF 10/28'!A:P;'WEEK OF 10/21'!A:P;'WEEK OF 10/14'!A:P;'WEEK OF 10/07'!A:P;'WEEK OF 09/30'!A:P;'WEEK OF 09/23'!A:P;'WEEK OF 09/16'!A:P;'WEEK OF 09/09'!A:P;'WEEK OF 09/02'!A:P},
"Select * where Col11 = 'RD' order by Col2 desc",0)
I would like to build a reference to an array that will auto-populate a concatenation based on the day.
Using the following code I can have the concatenate give me the array I need,
=if(H4<=today(),CONCATENATE("'",H$1,text(H4,"mm/dd"),"'!A:P;",),"")
but when I try to input it into the query function it just returns the concatenated text:
=QUERY(I1,"Select *")
'Week of 01/06'!A:P;'Week of 01/13'!A:P
I have tried with and without the curly brackets with no success.
I would like the sheet to be able to refresh and see that it is the correct day, the new sheet name is populated and the query gets updated.
I need help with making I1 work.
Link to Test Query Sheet
dudes who copy-pasted INDIRECT function into Google Sheets completely failed to understand the potential of it and therefore they made zero effort to improve upon it and cover the obvious logic which is crucial in this age of arrays.
in other words, INDIRECT can't intake more than one array:
=INDIRECT("Sheet1!A:B"; "Sheet2!A:B")
nor convert an arrayed string into active reference, which means that any attempt of concatenation is also futile:
=INDIRECT(MasterSheet!A1:A10)
————————————————————————————————————————————————————————————————————————————————————
=INDIRECT("{Sheet1!A:B; Sheet2!A:B}")
————————————————————————————————————————————————————————————————————————————————————
={INDIRECT("Sheet1!A:B"; "Sheet2!A:B")}
————————————————————————————————————————————————————————————————————————————————————
=INDIRECT("{INDIRECT("Sheet1!A:B"); INDIRECT("Sheet2!A:B")}")
the only possible way is to use INDIRECT for each end every range like:
={INDIRECT("Sheet1!A:B"); INDIRECT("Sheet2!A:B")}
which means that the best you can do is to pre-program your array like this if only part of the sheets/tabs is existant (let's have a scenario where only 2 sheets are created from a total of 4):
=QUERY(
{IFERROR(INDIRECT("Sheet1!A1:B5"), {"",""});
IFERROR(INDIRECT("Sheet2!A1:B5"), {"",""});
IFERROR(INDIRECT("Sheet3!A1:B5"), {"",""});
IFERROR(INDIRECT("Sheet4!A1:B5"), {"",""})},
"where Col1 is not null", 0)
so, even if sheet names are predictable (which not always are) to pre-program 100+ sheets like this would be painful (even if there are various sneaky ways how to write such formula under 30 seconds)
an alternative would be to use a script to convert string and inject it as the formula
A1 would be formula that treates a string that looks like real formula:
=ARRAYFORMULA("=QUERY({"&TEXTJOIN("; ", 1,
IF(A3:A<>"", "'Week of "&LEFT(A3:A, 5)&"'!A1:D5", ))&
"}, ""where Col1 is not null"", 1)")
further populating of A6:A will expand the string automatically
then this script will take the string from A1 cell and it will paste it as valid formula into C5 cell:
function onEdit() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Master Sheet');
var src = sheet.getRange("A1");
var str = src.getValue();
var cell = sheet.getRange("C5");
cell.setFormula(str);
}
of course, the script can be changed to onOpen trigger or with custom name triggered from the custom menu or via button (however it's not possible to use the custom function as formula directly)
If you're trying to update the data your query is looking at and you're feeding it a string, you need to put that string within the indirect() function. That will interpret your string as a data reference and point your query() in the right direction.
So for this you'd probably have
=QUERY(INDIRECT(I1),"Select *")

Tabulate JSON into Sheets

I've been trying to get a readable database of a JSON file from a URL.
I've used fastfedora's script on Github, https://github.com/fastfedora/google-docs/blob/master/scripts/ImportJSON/Code.gs, to import JSON from the URL to Sheets. I'm using the basic:
=TRANSPOSE(ImportJSON("https://rsbuddy.com/exchange/summary.json"))
I used transpose as it was easier to work with two long columns rather than two long rows.
The data that's been imported however, is very messy: https://docs.google.com/spreadsheets/d/1mKnRQmshbi1YFG9HHg7-mKlZZzpgDME6-eGjDJKzbRY/edit?usp=sharing. It's basically 1 long column of descriptive data, (name, id, price etc.) and another column of the variable (the actual name of the item and it's price in digits).
Is it possible to manipulate the resultant Sheets page so that the common factors in the first column can be lined up with the pseudo-table beside two initial columns? E.g. for the first item, the ID will be '2', the name will be 'Cannonball', the Sp will be '5' etc.
Thanks in advance. Do forgive me for my ignorance.
Example
Simple formula
I think, faster way to get IDs:
=QUERY(QUERY(A2:B,"select B where A <> '' offset 4"),"skipping 7")
and if you want Names:
=QUERY(QUERY(A2:B,"select B where A <> '' offset 1"),"skipping 7")
when you change offset from 0 to 6, you get different columns
outputs.
7 is the number of columns in Data.
The result is autocompleted column with Data.
Hard formula
Also possible to get the whole result with one formula:
paste =COUNTA(A:A) in cell E2
paste 7 in E3, this is the number of columns in Data
=E2/E3 in E4
And then in cell G2 or somewhere on right paste the formula:
=ArrayFormula(vlookup(if(COLUMN(OFFSET(A1,,,1,E3)),
(row(OFFSET(A1,,,E4))-1)*E3+COLUMN(OFFSET(A1,,,1,E3))),
{row(OFFSET(A1,,,E2)),OFFSET(B2,,,E2)},2,0))
It works slow, but gives the whole table.
or Script?
I've also tried to use script UDF function. Here's test formula:
=ConvertTo2D(TRANSPOSE(R3:R16),7)
where R3:R16 is small range which was splited into table with 7 columns. The script is pretty short:
function ConvertTo2D(Arr, index) {
var newArr = [];
while(Arr[0].length) newArr.push(Arr[0].splice(0,index));
return newArr;
}
Sounds good. But! It is ve-e-e-e-ery slow. So This solution is good only for quick test.
If the data is structured and every object will always have the same structure you can use a simple offset to do this:
=OFFSET($B$2,
(ROW($B2) - 2) * 7 +
COLUMN(D$1) - 4,
0)
Put that in D2 and drag to the right and down.
It is possible to immediately return the data in this fashion but for that you need to meddle with the script.