How to search a range for multiple pieces of text - excel

I need to search F$3 through F$96 for any cell that contain ALL FOUR of w3, x3, y3, and z3.
Return TRUE if ANY CELLS in f$3 to F$96 contain all four. how do?
Currently I use
=AND(ISNUMBER(SEARCH(W3,F$3:F$96)),ISNUMBER(SEARCH(X3,F$3:F$96)),ISNUMBER(SEARCH(Y3,F$3:F$96)),ISNUMBER(SEARCH(Z3,F$3:F$96)))
But if i place this formula in AA3, it only checks f3, not f$3 through f$96
I need it to check ALL the cells in that range and return true if ONE contains all 4 criteria.

SUMPRODUCT and -- (double negative) are useful to do what you want. As SUMPRODUCT expects an array of values, all cells are checked.
This is what I produced as an example (split into multiple lines for readability):
=(SUMPRODUCT(--(F$3:F$96=W3))>0)+
(SUMPRODUCT(--(F$3:F$96=X3))>0)+
(SUMPRODUCT(--(F$3:F$96=Y3))>0)+
(SUMPRODUCT(--(F$3:F$96=Z3))>0)
The -- converts all the TRUE/FALSE into 1's and 0's, and then adds them up (as we are only giving 1 list to each SUMPRODUCT, it doesn't do any multiplication, it just adds). The value returned will be the number of cells that matched the value you are looking for.
As we don't care how many matched, just that at least one matched, we complare result of the SUMPRODUCT to see if we got at least one match (>0), and all the test results are added together.
The result of this calculation would be 4 if all the numbers are found, 3 if only three are found, and so on.
You can either test for the 4 result, or give people an idea of how many they had match by just giving them the result.

Related

SUMIF (or something) over a wide range of columns

I've got a massive parts spreadsheet that I'm trying to simplify. Various parts could be included in number of locations, which I would like to add up to a single list. The attached file is just an example using reindeer.
This is doable with using a bunch of SUMIF statements added together, but not practical due to the range of columns I need to include. There's gotta be a better way!?
=SUMPRODUCT(--($D$4:$J$11=$A4),$E$4:$K$11))
SUMPRODUCT can do that. Make sure the second range shifts one column, but has equal count of columns (and rows).
($D$4:$J$11=$A4) results in an array of TRUE's or FALSE's for the value in range $D$4:$J$11 being equal to the value in $A4 (no $ prior to it's row number will increase the row # referenced when dragged down).
Adding -- in front of the array converts the TRUE's and FALSE's to 1's and 0's respectively.
Multiplying that with the range to the right of it will result in 1* the value in $E$4:$K$11 for all TRUE's, which results in it's value, or 0* the value in $E$4:$K$11 for all FALSE's, which results in 0.
Summing the array of values results in the sum of all values where the condition is met in the column left from it.
SUMPRODUCT combines the multiplication of the array and summing the array results to 1 total sum.
You can use simply the SUM:
=SUM((D$4:$D$11=A4)*$E$4:$E$11,($F$4:$F$11=A4)*$G$4:$G$11, etc.)
where in etc you can put any range you want. If you don't use 2021/365 version, you must confirm the formula with CTRL+SHIFT+ENTER.

How to regexmatch a range?

I am trying to take a data from a table and get the value of how much a class gets a point. I used VLOOKUP to do this, but the problem is that I have to tell the sheets on which class gets how much.
The data:
Your data seems to be setup in a way that unnecessarily complicates things.
kelas-column isn't showing the class, but name and class. For easy use in calculation this would better be divided in two columns: name | class
poins-column seems to be numbers formatted as text (judging by the leading +) if it was showing the number only and the class would show the actual class, a simple SUMIF would solve your problem.
Now it's still doable using SUMPRODUCT:
=SUMPRODUCT(--(A17=RIGHT($B$2:$B$11,2)),--($D$2:$D$11))
The first part checks if the search value A17 equals the last 2 digits in range B2:B11 (the $'s in the formula are to lock the range when dragging the formula down or aside).
This results in an array of TRUE's and FALSE's which is converted to 1's and 0's by the leading --.
The second part simply converts the text values to numbers using the same logic as with the TRUE's and FALSE's, using the --.
SUMPRODUCT multiplies the first array with the second array and adds it all up.
If a condition is true it multiplies the value of the points column by 1 (equals the points), if false it multiplies by 0 (equals 0).
In the end it sums all values meeting given condition.

Why is =SUMIF(C5:C19,NOT(ISFORMULA(C5:C19))) returning zero?

I have a spreadsheet that I track my hours. Each cell initially is populated with a formula, i.e. =IF(WORKDAY(B24-1,1,holidays2019)=B24,OFFSET(C24,-1,2),0)
and then as the month progresses I enter my actual time.
In the following excerpt all values through 5/10/2019 are entered.
The formula =SUMIF(C5:C19,NOT(ISFORMULA(C5:C19))) shows zero. I do not understand why this does not work.
I appreciate any help! Column B in my spreadsheet corresponds to the dates shown below and Column C to the time entries.
Expected Result: 48.9
=SUMPRODUCT(J6:J20,--NOT(ISFORMULA(J6:J20)))
The key to this solution is the -- in front of the NOT(). A boolean that is processed by a math operator gets converted to 1 or 0. --, +0, -0, *1, /1 would have all worked to do the conversion. So now you wind up with an array of values you may want to sum being multiplied by an array of 1 and 0 to indicate the ones you want. The 1 are manual entry and the 0 are your formulas entries.
Now SUMPRODUCT performs array like calculations. As a result avoid using full column/row references inside it or you will wind up with a lot of excess calculations. Adjust the ranges in the answer to suit your needs.
Here's the MSDN definition of the Criteria in =SUMIF
criteria Required. The criteria in the form of a number, expression,
a cell reference, text, or a function that defines which cells will be
added. For example, criteria can be expressed as 32, ">32", B5, "32",
"apples", or TODAY().
Important: Any text criteria or any criteria that includes logical or
mathematical symbols must be enclosed in double quotation marks (").
If the criteria is numeric, double quotation marks are not required.
So, the reason, why your SUMIF returns 0 is, because none of the cells match the criteria, as they return a number and meanwhile they expect FALSE
Another issue here being, that the ISFORMULA will return TRUE, even when a range contains a single formula while all the rest has none. So basically you need to drag the formula down for each cell individually and sum them up only when a value is TRUE
Starting from cell D1:
=ISFORMULA(B1)
And then you can simply sum them up with the formula you provided.
=SUMIF(D1:D16,TRUE,C1:C16)
Obviously, you can hide the column D to make it more aesthetically pleasing.
Your formula fails because the criteria you're matching against, is TRUE/FALSE. Obviously the values in C5:C19 don't contain any booleans, so the sum is 0.
To solve this, you can add the correct criteria in cell D5 and below: =ISFORMULA(C5)
Then use =SUMIF(D5:D19,FALSE,C5:C19) to sum the values in column C.

What is this programmer doing with his Lookup function?

I found on a forum a formula to find the last populated cell in a column:
LOOKUP(2,1/(G:G<>""),ROW(G:G)))
But what's going on with this bit?
1/(G:G<>"")
One divided by ??? (something that's not equal to ""?) I don't understand the logic, here.
If you want to observe the calculation step by step by evaluating the formula with Formula Auditing I strongly recommend limiting the range. Say apply:
=LOOKUP(2,1/(G1:G10<>""),ROW(G1:G10))
And, for illustration purposes, populate no lower down the sheet than say G6 (but a void between, in the range G1:G5, may in that case help to understand what is happening).
For this answer I am only going to consider five cells: G1, G3 and G4 populated, G2 and G5 (onwards) not.
1/(G1:G5<>"")
Is indeed at the heart of this formula. G1:G5<>"" does, as you have recognised, test whether not equal to "". "" is the convention for 'empty' for an Excel cell. If populated (ie "not empty") this returns TRUE and FALSE otherwise. Hence for the five cells as chosen for this example an array is returned, regarding G1:G5 in order, of:
TRUE;FALSE;TRUE;TRUE;FALSE.
In arithmetic calculations Excel treats TRUE as 1 and FALSE as 0. Hence using the above truth table as the denominator and 1 as the numerator gives an array (again in order) of:
1/1;1/0;1/1;1/1;1/0
which resolves to:
1;#DIV/0!;1;1;#DIV/0!.
In the LOOKUP function above 2 was chosen as the lookup_value. (Any other number greater than 1 would serve equally well.) So we are looking for 2 in an array that is composed exclusively of either 1s or errors. Therefore there is no chance of finding an exact match, so the default kicks in, which is the last value (in order, not counting errors). The last 1 in the array is the fourth element, and the fourth element in ROW(G1:G5) is …4.
G4 is the last populated cell in ColumnG (in my example).

Explain LOOKUP formula

I'm trying to understand some legacy Excel file (it works, but I would really like to understand how/why it's working).
There is a sheet for data input (input sheet)and some code that is called to process data in the input sheet. I found out that number of rows in the input sheet is determined using a Lookup formula like this:
=LOOKUP(2;1/('Input sheet'!E1:E52863<>"");ROW(A:A))
"E" column contains names for import items and column is NOT sorted
"A" column does not contain anything special - I can replace it with B, C or whatever column and it does not affect the formula's outcome
According to what I have found about Lookup behaviour: •If the LOOKUP function can not find an exact match, it chooses the largest value in the lookup_range that is less than or equal to the value.
What does this ^-1 operation to the specified range? If E(x) is not empty -> it should turn into 1, but if it is empty - then it would be 1/0 -> that should produce #DIV/0! error...
1/('Input sheet'!E1:E52863<>"")
The outcome is the same, if I replace 2 with any positive number (ok, tried only some, but it looks like this is the case). If I change lookup value to 0, then I get #N/A error -> •If the value is smaller than all of the values in the lookup_range, then the LOOKUP function will return #N/A
I am stuck... can anyone shed some light?
LOOKUP has the rare ability to ignore errors. Conducting the 1/n operation will produce an error every time n is zero. False is the same as zero. So, for your formula, every empty cell produces an error in this calculation. All of those results are put in a vector array in the 2nd argument.
Searching for any positive value (the 1st argument) larger than 1 will result in LOOKUP finding the last non-error value in the above vector.
It also has the nice optional 3rd argument where you can specify the vector of results from which to return the lookup value. This is similar to the INDEX component of the the INDEX/MATCH combo.
In the case of your formula, the 3rd argument is an array that looks like this: {1;2;3;4;5;6;7;8;9;...n} where n is the last row number of the worksheet, which in modern versions of Excel is 1048576.
So LOOKUP returns the value from the vector in the 3rd argument that corresponds to the last non-error (non-blank cell) in the 2nd argument.
Note that this method of determining the last row will ignore cells that have formulas that result in a zero-length string. Such cells look blank but of course they are not. Depending on the situation, this may be precisely what you want. If, on the other hand you want to find the last row in column E that has a formula in it even if it results in a zero-length string, then this will do that:
=MATCH("";'Input sheet'!E:E;)
You might get some idea what the formula is doing (or any other formula) if you apply Evaluate Formula. Though since the principle is the same whether 3 rows or 52863 I'd suggest limiting the range, to speed things up if choosing Evaluate Formula. As usual with trying to explain formulae, it is best to start from the inside and work outwards. This:
'Input Sheet'!E1:E52863<>""
returns an array with a result for every entry in ColumnE from Row1 to Row52863. Since it is a comparison (<> does not equal) the result is Boolean - ie TRUE (not empty) or FALSE (is empty). So if only the first half of E1 to E52863 is populated, the result is {TRUE;TRUE;TRUE; ... and a LOT more TRUE; ... and FALSE ... and a LOT more ;FALSE and finally }.
Working outwards, the next step is to divide this array into 1. In arithmetic operations Boolean TRUE is treated as 1 and FALSE as 0, so the resultant array is {1;1;1; ... and a LOT more 1; ... and #DIV/0!... and a LOT more ;#DIV/0! and finally }.
This then becomes the lookup_vector within which LOOKUP seeks the lookup_value. The lookup_value you show is 2. But the array comprises either 1 or #DIV/0! - so 2 will never be found in it. As you have noticed, that 2 could just as well be 3, or 45 or 123 - anything as long as not a value present in the array.
That (not present) is necessary because LOOKUP stops searching when it finds a match. The fact that there is no match forces it to the end of the (valid) possibilities - ie the last 1. At this point, in my opinion, it would be logical to return "not found" but - I suspect merely a quirk, though very convenient - it returns that 1 - by its index number in the list, ie 52863 if all cells in E1:E52863 are populated.
Although the result_vector (Row(A:A)) is optional for LOOKUP it is required in this usage in effect to fix the start point for the index (effectively Row1, since an entire column). You might change that to say A3:A.. and the result would be the number of the highest populated row number in ColumnE plus 2 (3 -1).

Resources