Is there a way to specify an input is a single cell in Google Sheets? - google-sheets

I want to iterate over an array of cells, in this case B5:B32, and keep the values that are equal to some reference text in a new array.
However, SPLIT nowadays accepts arrays as inputs. That means that if I use the array notation of "B5:B32" within ARRAYFORMULA or FILTER, it treats it as a range, rather than the array over which we iterate one cell at a time.
Is there a way to ensure that a particular range is the range over which we iterate, rather than the range given at once as an input?
What I considered was using alternative formulations of a cell, using INDEX(ROW(B5), COLUMN(B5)) but ROW and COLUMN also accept array values, so I'm out of ideas on how to proceed.
Example code:
ARRAYFORMULA(
INDEX(
SPLIT(B5:B32, " ", 1), 1
) = "Some text here"
)
Example sheet:
https://docs.google.com/spreadsheets/d/1H8vQqD5DFxIS-d_nBxpuwoRH34WfKIYGP9xKKLvCFkA/edit?usp=sharing
Note: In the example sheet, I can get to my desired answer if I create separate columns containing the results of the SPLIT formula. This way, I first do the desired SPLITS, and then take the values I need from that output by specifying the correct range.
Is there a way to do this without first creating an output and then taking a cell range as an input to FILTER or other similar functions?
For example in cell C35 I've already gotten the desired SPLIT and FILTER done in one go, but I'd still need to find a way to sum up the values of the first character of the second column. Doing this requires that I take the LEFT value of the second column, but for that I need to output the results and continue in a new cell. Is there a way to avoid this?

Ralph, I'm not sure if your sample sheet really reflects what you are trying to end up with, since, for example, I assume you are likely to want the total of the hours per area.
In any case, this formula extracts all of the areas, and the hours worked, and is then easy to do further calculations with.
=ArrayFormula({REGEXEXTRACT({C5:C9;D5:D9;E5:E9;F5:F9;G5:G9;H5:H9},"(.*) \d"),
VALUE(REGEXEXTRACT({C5:C9;D5:D9;E5:E9;F5:F9;G5:G9;H5:H9}," (\d+)hrs"))})
Try that in cell E13, to see the output.
The first REGEXEXTRACT pulls out all the text in front of the first space and number, and the second pulls out all the digits in a string of " #hr" in each cell. These criteria could be modified, if necessary, depending on your actual requirements. Note that it requires the use of VALUE, to convert the hours from text to numeric values, since REGEXEXTRACT produces text (string) results.
It involved concatenating your multiple data columns into one long column of data, to make it simpler to process all the cells in the same way.
This next formula will give you a sum, for whatever matching room/task you type into B6, as an example.
=ArrayFormula(QUERY({REGEXEXTRACT({C5:C9;D5:D9;E5:E9;F5:F9;G5:G9;H5:H9},"(.*) \d"),
VALUE(REGEXEXTRACT({C5:C9;D5:D9;E5:E9;F5:F9;G5:G9;H5:H9}," (\d+)hrs"))},
"select Col1, sum(Col2) where Col1='"&B6&"' group by Col1 label sum(Col2) '' ",0))

I will also answer my own question given what I know from kirkg13's answer and other sources.
Short answer: no, there isn't. If you want to do really convoluted computations with particular cell values, there are a few options and tips:
Script your own functions. You can expand INDEX to accept array inputs and thereby you can select any set of values from an array without outputting it first. Example that doesn't use REGEXMATCH and QUERY to get the SUM of hours in the question's example data set: https://docs.google.com/spreadsheets/d/1NljC-pK_Y4iYwNCWgum8B4NJioyNJKYZ86BsUX6R27Y/edit?usp=sharing.
Use QUERY. This makes your formula more convoluted quite quickly, but is still a readable and universally applicable method of selecting data, for example particular columns. In the question's initial example, QUERY can retrieve only the second column just like an adapted INDEX function would.
Format your input data more effectively. The more easily you can get numbers from your input, the less you have to obfuscate your code with REGEXMATCHES and QUERY's to do computations. Doing a SUM over a RANGE is a lot more compact of a formula than doing a VALUE of a LEFT of a QUERY of an ARRAYFORMULA of a SPLIT of a FILTER. Of course, this will depend on where you get your inputs from and if you have any say in this.
Also, depending on how many queries you will run on a given data set, it may actually be desirable to split up the formula into separate parts and output partial results to keep the code from becoming an amalgamation of 12 different queries and formulas. If the results don't need to be viewed by people, you can always choose to hide specific columns and rows.

Related

How do I create a formula that recommends a matchup of 2 names?

I’m trying to make a formula that accomplishes this:
From a list of numbers, find the pairs of numbers with the lowest difference and second lowest difference, and write their differences elsewhere(I don’t know how to do this)
Use those numbers to find and use the value(a name)of the cell to their left(I don’t know how to do this with duplicate numbers)
How would I go about this?
The final product should include all 4 numbers, names, and both differences.
In the picture below, the pink shaded section is the goal.
What I did is to first SORT the values:
=SORT(A2:B,2,1)
Then, wrapped it in LAMBDA (in order not to repeat those formula again and again), and started "scanning" those values to find the differences. Since it's already sorted, the "smallest" will be found in this comparison.
For this, I used MAP. Used SEQUENCE, COUNTA and INDEX in order to find the amount of values in the first column; and SEQUENCE will help me do the "navigation". With the variable resultant "p" I searched each row with the next one (p+1). Resulting in something like this:
=LAMBDA(sorted,MAP(SEQUENCE(COUNTA(INDEX(sorted,,1))-1),LAMBDA(p,{INDEX(sorted,p,1),INDEX(sorted,p+1,1),INDEX(sorted,p+1,2)-INDEX(sorted,p,2)})))(SORT(A2:B,2,1))
With that, you're already one step away. Just with SORTN you can find the four smallest differences:
=LAMBDA(diff,SORTN(diff,4,1,3,1))
(LAMBDA(sorted,MAP(SEQUENCE(COUNTA(INDEX(sorted,,1))-1),LAMBDA(p,{INDEX(sorted,p,1),INDEX(sorted,p+1,1),INDEX(sorted,p+1,2)-INDEX(sorted,p,2)})))
(SORT(A2:B,2,1)))
I hope it's already useful! You can split those values in two columns, obviously; just using INDEX to access the desired row of this formula; or just locate the formula somewhere and refer to those cells. Let me know if it's useful!
you can try:
=LAMBDA(z,SORTN(MAP(INDEX(z,,1),INDEX(z,,2),LAMBDA(a,b,{a,b,ABS(XLOOKUP(a,A:A,B:B,)-XLOOKUP(b,A:A,B:B,))})),4,0,3,1))(INDEX(SPLIT(QUERY(UNIQUE(MAP(LAMBDA(z,FLATTEN(z& "🐠" &TRANSPOSE(z)))(FILTER(A2:A, A2:A<>"")),LAMBDA(y,JOIN("🐠",SORT(UNIQUE(TRANSPOSE(SPLIT(y,"🐠")))))))),"Select Col1 Where Col1 CONTAINS '🐠'"),"🐠")))

How to apply multiple conditions from one cell for SUMIF | GoogleSheets

Do you have an idea for a function that would sum the amounts from table 2 based on Unique_nr from Table 1?
I tried to do it this way:
=SUM(ARRAYFORMULA(SUMIF(E3:E9,{SPLIT(A3,",")},F3:F9))) <---doesn't work
=SUM(ARRAYFORMULA(SUMIF(E3:E9,{"8-1","9-1"},F3:F9))) <----It works
Theoretically the SPLIT() function gives the same result as I type manually, but unfortunately it doesn't work.
I would like to do this with one function for the entire range of data
https://docs.google.com/spreadsheets/d/1JGvFIZIE6c_D0A2Z4xCWf7pxqVft4Zsb6S-45_d9LY4/edit?usp=sharing
You were almost in the correct way
First of all, remove the double quotes from the cells.
By default SPLIT will Divide text around a specified character or string and it means there will be an extra step in order to use this output to another function, it's possible that your cell had an extra character and the TRIM function will solve it.
=SUM(ARRAYFORMULA(SUMIF(E3:E9,{trim(SPLIT(A3,","))},F3:F9)))
You can use VLOOKUP and SUM as a different approach
As you mentioned SPLIT is a good approach to treat comma-separated cells. In order to avoid unexpected spaces TRIM is a good option (it's optional) as well as IFNA in order to fill that cell in case there's not a match.
=ArrayFormula(SUM(IFNA(vlookup(trim(split(A3,",")),E3:F9,2,0))))
If you can't find a better option, you can use a dragable formula:
=ArrayFormula(SUM($F$3:F*(ISNUMBER(SEARCH($E$3:E,A3)))))

Sort Google Sheet by order values are entered in a data validation

Is there a way to sort a Google Sheet by the order in which values are entered into a data validation criteria?
I want to sort the sheet based in ascending order Low,Medium,High or descending order High,Medium,Low. Not by alphabetical order High,Low,Medium and Medium,Low,High respectively.
Aaron. The easiest way would be to use a helper column (which you can hide later if you like) wherein you assign numerical values to your Low, Medium and High (presumably 1, 2 and 3 respectively). Then you sort using the numerical column. It's fairly easy to write a one-cell array formula that would assign the numerical values to your labels. The numerical column need not be beside the label column; it can be any column.
Without seeing an actual sample sheet, I can't show you. But hopefully the concept is clear, and you can take it from there.
Added description after sheet was shared:
In the example sheet, Sheet1 Column A contained the Priority in words (Low, Medium, High) and Column B contained "other data." I placed the following array formula into C1:
=ArrayFormula({"Priority Val";IF(A2:A="","",VLOOKUP(A2:A,Data!A:B,2,FALSE))})
The formula is an array formula, hence the ArrayFormula() wrap.
Inside this are curly brackets {} which allow the building of arrays that are not "of a type." In this case, the header is listed first ("Priority Val"). The semicolon means "place the next part underneath." Then a VLOOKUP references every value in Column A (i.e., the priority words) against a simple chart in a second sheet named "Data." In that "Data" sheet, Column A simply lists 1, 2, 3 and Column B lists your exact words: Low, Medium, High. The IF() function just checks to see if a row in Sheet1!A:A is blank. If so, a null is assigned before trying the VLOOKUP; otherwise, every blank row would show an #NA error.
If you want to make it even more air tight, it's good practice to wrap VLOOKUP in IFERROR(), just in case you misspell something in Sheet1!A:A. That would look like this:
=ArrayFormula({"Priority Val";IF(A2:A="","",IFERROR(VLOOKUP(A2:A,Data!A:B,2,FALSE)))})
And you can avoid misspelling by applying data validation to Sheet1!A2:A, referencing Data!A:A as the only allowable answers. This is not strictly necessary; but I have done it in the sample sheet to show you.

Randomize cells in Google Sheets

Is there a formula to randomize a column of data which keeps each item represented only once (has the same items)?
So:
APPLES
PEARS
BERRIES
Might come out as
PEARS
BERRIES
APPLES
Randbetween formulas no good here, as you might get two 'PEAR's.
There is a new "randomize range" feature available in the context menu after selecting a range:
]
The following approach implements the idea of pnuts, but without creating a column filled with random numbers:
=query({A2:A20, arrayformula(randbetween(0, 1e20 + row(A2:A20)))}, "select Col1 order by Col2", 0)
Here A2:A20 is the range to be permuted. The arrayformula generates a random integer for each. The query sorts the array by those random integers, but does not put the random numbers in the spreadsheet.
The entropy of randbetween is 64 bits, so collisions are extremely unlikely. And even if two random numbers happen to be equal, that will not generate repetitions; sorting by whatever column never does that. It only means the corresponding pair of entries will appear in their original order.
Came across this while looking for a formula to generate a set of random unique integers and ended up devising my own, so I'm leaving it here for anyone else looking for the same:
=SORT(SEQUENCE(A$1),RANDARRAY(A$1),FALSE) where A$1 is the count of integers to generate (expressed here as a cell reference because I like to create sheets where I can input a number in a cell rather than changing the formula, but this can of course be just a number.)
This can be expanded by adding the three other fields to SEQUENCE as explained in the function's documentation, or by wrapping it in an ARRAYCONSTRAIN to limit the count of entries returned without changing the minimum or maximum values of the generated entries. Hope all this makes sense!
I adopted a similar approach to user6655984 before I found this post.
RANDARRAY seemed to be a neat call once solution.
I had similar demands. Formula based, randomized return order, ability to have only unique records or not as the whim took me.
Right clicking to randomize range meant user interaction I didn't want and the data is dynamic.
I built in the random numbers into a query data range on the fly.
I get the flexibility of query (can easily expand the range, add returned columns filter criteria etc), I don't have to show the random numbers at all and can wrap it in UNIQUE if desired, it re-randomizes with each recalc.
Have some data in column A2:A.
To see the inline data range.
={RANDARRAY(ROWS($A$2:$A)),$A$2:$A}
Query (inc duplicates), filter out empty.
=QUERY({RANDARRAY(ROWS($A$2:$A)),$A$2:$A},"SELECT Col2 WHERE COL2<>'' ORDER BY Col1 ",0)
Same but wrapped by unique.
=UNIQUE(QUERY({RANDARRAY(ROWS($A$2:$A)),$A$2:$A},"SELECT Col2 WHERE COL2<>'' ORDER BY Col1 ",0))
Hope it helps someone, even if years later. :)
Matt

Google Docs - SUMIF - SUM range if single cell contains a string

I'd like to quickly include or exclude an entire range of values in a SUM.
Presently I'm SUMing select cells for a grand total: [E19] =SUM(E13,E20,E30,E45,E55,E70,E80)
These are in turn SUMs of selected ranges:
... [E30] =SUM(E31:E44), [E55] =SUM(E56:E69), ...etc.
One of these ranges I would like to toggle it's inclusion in the Grand Total.
It seemed the best way to do it was this:
[E45] =SUMIF(D45,"β˜‘",E46:E54)
In short, in cell E45 I'd like to SUM E46 to E54 only if D45 contains a β˜‘.
However Google Doc's SUMIF seems to only work with matched ranges: =SUMIF(D46:D54,"β˜‘",E46:E54)
Is there a way to SUM a range only if a specific value exists in a single cell?
You're right about SUMIF, it allows you to sum values from a range, which meet a certain criteria (on another range of the same length). For example, if you had two columns called "status" and "price", you could use it to sum all the prices for a given status.
What you're trying to do can be done, instead, with the use of the IF function:
=IF(D45="β˜‘";SUM(E46:E54);0)
If the condition specified in the first argument is true, it will return the second argument, that is, the sum. Otherwise, it will return the third argument, 0.
After working through the logic to share the issue I wound up identifying a solution. Rather than trying to force SUMIF to check a single cell against a range. I just nested the 1:1 SUMIF inside my 'Grand SUM': =SUM(E13,E20,E30,SUMIF(D45,"β˜‘",E45),E55,E70,E80).

Resources