excel - count if multiple words are in a cell - excel

I have values
AA,BB,CC
AA,CC
AA
AA,BB
BB
BB,CC
CC
CC,AA
CC,BB
BB,CC,DD
find all cells that have. how do I search for each values.
AA,BB = 2
BB,CC = 4
Example
COUNTIFS($A:$A,"*AA*",$A:$A,"*BB*") doesn't seem to work.

You could try this using wildcards * with TEXTBEFORE() & TEXTAFTER()
• Formula used in cell D2
=COUNTIFS(A1:A10,"*"&TEXTBEFORE(C2,",")&"*",A1:A10,"*"&TEXTAFTER(C2,",")&"*")
EDIT
As suggested by Tom Sharpe Sir,
• Formula used in cell D2
=LET(x,TEXTSPLIT(C2,","),y,COUNTA(x),
SUM(--(MMULT(N(ISNUMBER(SEARCH(x,$A$1:$A$10))),SEQUENCE(y,,1,0))=y)))

You could try:
Formula in D2:
=MAP(C2:C5,LAMBDA(z,SUM(MAP(A1:A11,LAMBDA(x,LET(y,TEXTSPLIT(z,,","),N(SUM(N(TEXTSPLIT(x,",")=y))=ROWS(y))))))))
Note: My answer assumes no duplicates in the values in column A:A. e.g.: AA,AA.

How about:
=LET(searchvalues, C2,
data, $A$1:$A$10,
split, TEXTSPLIT(searchvalues,","),
count, COLUMNS(split),
SUM(
--(MMULT(
--ISNUMBER(SEARCH(split,data)),
SEQUENCE(count,,1,0))
=count)))
It splits the values you want to search (stored in C2 in my example) into individual values: split
Than split is searched within each row of your data.
This returns TRUE or FALSE wrapped in -- changes TRUE to 1 and FALSE to 0.
This is used within MMULT and this returns the sum of the occurrences of each individual split value. Finally the MMULT result needs to equal the number of splitted search values.
The sum of this being true is the end result.

The following approach considers a variable number of words to search, not just 2 words as in the input sample:
=LET(lk, B1, A, $A$1:$A$11, lks, TEXTSPLIT(lk,, ","),
byr, BYROW(A, LAMBDA(x,SUM(COUNTIF(x,"*"&lks&"*")))), SUM(N(byr=ROWS(lks))))
It has a caveat that if the word is repeated more than one time per row in the first column, it is counted as 1, as you can see in the following output. This is because of how COUNTIF (or COUNTIFS) works with wildcards (other answers provided using SEARCH produce the same result). If that assumption is ok, then it works. The rest is just to drag the formula down (formula1).
UPDATE: Considering #JvdV's comment, to avoid false positive when the word to search could be a substring of the column A on a given row. Like for example, searching the word AA, in the string: AAA will produce a false positive. The following version avoids it:
=LET(lk, B1, A, $A$1:$A$11, lks, TEXTSPLIT(lk,, ","),
byr, BYROW(A, LAMBDA(x, SUM(N(TEXTSPLIT(x,",") = lks)))), SUM(N(byr=ROWS(lks))))
Here is the output:
I added intentionally the highlighted cases to test additional situations. Row 11 repeats the word: AA, and BB, but it is counted as 1 in the final result.
The following approach tries to identify the total number of counts considering repetitions of the word in column A (formula2):
=LET(lk, B1, A, $A$1:$A$11, lks, TEXTSPLIT(lk,, ","),
byr, BYROW(A, LAMBDA(x, LET(match, IFERROR(TOCOL(XMATCH(TEXTSPLIT(x, ","),
lks),2),0), ux, UNIQUE(match), IF(ROWS(ux) < ROWS(lks), 0,
MIN(MMULT(TRANSPOSE(N(match = TOROW(ux))), SEQUENCE(ROWS(match),,1,0))))))),
SUM(byr))
Now we get the following result:
Now we get an additional count for the case of AA, BB.
In formula2, match has the index position as a result of the XMATCH call, we use TOCOL to remove non-found values #N/A. In case no words were found, we use IFERROR to assign the zero value. The IF condition:
IF(ROWS(ux) < ROWS(lks)
Ensures to calculate non-zero counts only if all words were found. We use MMULT to calculate per row the number of repetitions of the lookup words. We take the minimum, to ensure we only consider the scenarios where all the words are present. There could be a situation, where one of the lookup words has more counts than another one, which is why we take the minimum. Therefore we are counting the entire set of lookup words found regardless of the order,

Answer was
COUNTIFS($A:$A,"*"&$C$2&"*",$A:$A,"*"&$C$3&"*")
C2 = AA
C3 = BB

Related

Numbering Based on Condition(s)

I'm trying to create auto numbering for Agents that are currently present and has numbers including zeroes 0 in 3rd or 4th column(zero meaning they don't get any stats but they are present)
Agents who has TEXT Value in the 3rd or 4th column are those who are not present (Ex: A = Absent, SL = Sick Leave, VL = Vacation Leave). Meaning, they should not be counted, therefore their value on 1st column should be blank, and therefore this should not stop the auto numbering for the rest of the agents below and should continue the count in sequence.
Can anyone help create formula that would fill the numbers on the 1st column automatically for those agents that are present and has value including 0 on column 3 or 4 (stats 1 or stats 2)?
To give more idea, I'm trying to show the current total number of agents who are currently present in this situation and will count their stats, and exclude all other agents who are not present and should not be counted.
Thank you!
Sequence Two Numeric Columns
Single Cell
In cell A3, a basic not spilling formula would be...
=IF(AND(ISNUMBER(C3),ISNUMBER(D3)),MAX(A$2:A2)+1,"")
... with the condition of a string in cell A2.
Without any conditions, you could try an improved version, similar to one of David Leal's suggestions:
=IF(AND(ISNUMBER(C3),ISNUMBER(D3)),
SUM(ISNUMBER(C$3:C3)*ISNUMBER(D$3:D3)),"")
Spill
In cell A3 you could use the following:
=LET(Data1,C3:C13,Data2,D3:D13,
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,""))
Line1: the inputs ('constants'), the same-sized single-column ranges
Line2: the zeros and ones, where the ones present the data of interest
Line3: the formula to replace the ones with the sequence and the zeros (errors due to division by zero) with an empty string
Converted to a LAMBDA, it could look like the following:
=LAMBDA(Data1,Data2,LET(
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,"")))(C3:C13,D3:D13)
Since it's such a long formula, you could create your own Lambda function by using this part...
=LAMBDA(Data1,Data2,LET(
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,"")))
... to define a name, e.g. SeqNumeric, when in the same cell, you could use
it simply with...
=SeqNumeric(C3:C13,D3:D13)
... instead.
Now you can use the function like any other Excel function anywhere in the workbook.
The Path
F3 =ISNUMBER(C3:C13)*ISNUMBER(D3:D13) - multiply: zeros-no, ones-yes
G3 =SCAN(0,F3#,LAMBDA(a,b,a+b)) - use the 'LAMBDA' helper function 'SCAN'
H3 =G3#/F3# - divide the 'scan' result by the zeros and ones
I3 =IFERROR(H3#,"") - convert the '#DIV/0!' errors to empty strings
The translation of the SCAN part could be something like the following:
Set the initial result a to 0.
Create a new array of the size of the initial array in F3#.
Loop through each element of the initial array, write its value to b, and replace a with the sum of a+b.
Write (the accumulated) a to the current element of the new array and repeat for the remaining elements of either array.
Return the new array.
Combine all of it in a LET.
J3 =LET(Data1,C3:C13,Data2,D3:D13,
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,""))
Convert to LAMBDA.
K3 =LAMBDA(Data1,Data2,LET(
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,"")))(C3:C13,D3:D13)
Copy the first part of the LAMBDA (note how it results in a #CALC! error since no parameters are supplied)...
L3 =LAMBDA(Data1,Data2,LET(
Data,ISNUMBER(Data1)*ISNUMBER(Data2),
IFERROR(SCAN(0,Data,LAMBDA(a,b,a+b))/Data,"")))
... and select Formulas -> Name Manager -> New to create your own function and finally use it with the following:
A3 =SeqNumeric(C3:C13,D3:D13)
You can try the following in cell A1:
=LET(B, B2:B12, C, C2:C12, f, 1*ISNUMBER(B*C),seq, SEQUENCE(ROWS(B)),
MAP(seq, LAMBDA(s, IF(INDEX(f,s)=0, "",SUM(FILTER(f, (seq<=s),0))))))
Here is the output:
A non-array version, expanding down the formula would be:
=IF(ISNUMBER(B2*C2), SUM(1*ISNUMBER(B$2:B2*C$2:C2)),"")
For the array version, it counts only if both columns Stat1 and Stat2 are numeric. The name f, has a value of 1 if the condition is TRUE, otherwise is 0. The MAP does the count if the index position of the f array is not zero, otherwise returns an empty string.
I think I got it.
This is the formula that I made
=IF(COUNTIFS(D2:BE2,"*",$D$1:$BE$1,TODAY())>0,"",MAX(A1:A$4)+1)
Countif criteria 1 = if the cell contains a letter and is counted > 0 then it will return blank, otherwise it will start the count using max function. The countif criteria 2 will will return the correct value according to the date today since the excel sheet has several data daily.

Count how many matches in the same row across 3 columns

I hope someone can help, I am looking for a formula solution to the following problem if possible.
I have a column of people's names, and for each of those people I have 3 columns of data from 3 different sources - I need to determine how many times the data in those 3 columns matches for each person. After extensive Googling, I could only find solutions where the result is summarised in a cell derived from a COUNTIF range, however I need the results summarised in the same row for each person.
For example:
"Dave" is in cell A2, his results were: column B2 = FAIL, C2 = PASS and D2 = PASS - so in this instance we have 2 matches as there were 2 passes.
"Sue" is in cell A3, her results were: column B3 = FAIL, C3 = FAIL and D3 = FAIL - so in this instance we have 3 matches as there were 3 Fails.
"Colin" is in cell A4, his results were: column B4 = TBA, C4 = FAIL and D4 = PASS- so in this instance we have 0 matches as none of the results match.
Ideally, I would like the number of matches listed down in column E for each individual person, so Dave's matching results would be cell E2, Sue's would be in E3 and Dave's in E4.
Many thanks in advance for your help.
Kindest regards,
TE
You could try:
Formula in E1:
=INDEX({0,2,3},MAX(COUNTIF(B1:D1,B1:D1)))
A bit of explaination for those who are curious:
COUNTIF(B1:D1,B1:D1) - Will result in an array of three values (1 per column), on how often these values appear in the three cells.
MAX() - Get's the max value from the previous array.
INDEX({0,2,3}) - Since the outcome of MAX() can only be 1-3 we can feed this as the row parameter into an INDEX() function. This will then result in either 0, 2 or 3.
A little less verbose and possibly more explicit would be:
=MIN(((B1=C1)+(C1=D1)+(B1=D1))*2,3)
With this last formula we use the fact that TRUE and FALSE are the equivalent of 1 and 0, and therefor we can add multiple boolean values. With some math we can then get our wanted result.
You can use IF() MAX() and COUNTIF combined.
In E2:
=IF(MAX(COUNTIF(B2:D2,B2),COUNTIF(B2:D2,C2),COUNTIF(B2:D2,D2))=1,0,MAX(COUNTIF(B2:D2,B2),COUNTIF(B2:D2,C2),COUNTIF(B2:D2,D2)))
So it does three separate countif to see how many is "duplicated" from each cell.
Takes the max of them and compare against 1, if that is true then return 0, else return what the max value was.
Would something like this work, in column E?
=if(countif(B2:D2,B2)=3,3,if(countif(B2:D2,B2)=2,2,if(countif(B2:D2,C2)=2,2,0)))
Let me know if that works for you.

Find items in a list that contain all sub-items

I have two lists as follows, Column A and Column D:
I would like to find all cells in Column A that do not contain a value from Column D.
For instance, A1 should be 0 because it contains the values 'a', 'b', 'c' and 'd' - all of which are in Column D.
A2 should be 1 because it contains the value 'h' - which is not in Column D.
My formula so far is very simple:
=COUNTIF(D1:D7,"*"&$A1&"*")
I'm guessing I could split the values in Column A to check, but am not too sure how.
I would like to avoid any VBA if possible.
Your question is not entirely clear to me, so far as what you want for results under different circumstances.
Your formula will return an array of values, so you need to account for that. The array consists of a 1 or a 0 depending on whether the character matches a letter in the D1:D7 range.
If you want to return the number of letters in your column "A" item that do NOT match an entry in Column "D", then try:
=LEN(A1)-SUMPRODUCT(COUNTIF(A1,"*"&$D$1:$D$7&"*"))
The SUMPRODUCT functions sums the array that the COUNTIF function is returning.
If you want something else, you will need to be more specific.
Cross-tabular layout
Using your logic, just with different layout of the data, you can achieve this:
Formula for B4 is: =COUNTIF(B$3;"*"&$A4&"*")
Formula for B1 is: =B2-SUM(B4:B10)
This is more along the lines of a comment, but I don't have enough reputation yet for comments.
The accepted answer from #ronrosenfeld will not work if the string in Column A contains repeated characters from the list in Column D. For example, if A1 contains "abca," it will return 1 rather than 0 because the array entry for "a" is 1 rather than 2 (it can only be 0 or 1).
So be aware that it only works if the letters are not repeated.
I cobbled a formula together based on some array magic I found by #ronrosenfeld here. (It seems so appropriate that Ron already got credit for answering this question, as my answer is a modification of another of his.)
The following formula works for any length of string in Column A and for any combination of letters including duplicates. It is entered as a regular formula:
=IFERROR(SUMPRODUCT(MATCH(MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1),D$1:D$7,0)=1),1)
You just enter it in B1, then copy it down as far as you like.
It works for strings of any length. If a cell is blank, it returns 1 because there is nothing there that appears in the list. If you want 0 for a blank cell, you can adjust the formula for that situation. Brute force approach:
=if(isblank(a1),0,IFERROR(SUMPRODUCT(MATCH(MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1),D$1:D$7,0)=1),1))

Formula to search through b c d and bring value of A

Looking for a formula to search a number of columns and rows, if they find a exact match to bring value of column A back.
This will be a large sheet with hundreds of rows down and approx 6 columns.
You may be able to perform this search by concatenating the values of each column into one 'super column', and then searching for your term with a wildcard. The first time that term comes up, you know the row, and the column it was in is irrelevant.
Note that this only works if 2 entries from adjacent columns couldn't create the search term incidentally. For example, 'cat' in cell A5 and 'dog' in B5 would concatenate to 'catdog', and would create the term 'atdo' between the 2nd & 5th characters. If 'atdo'was your search term, it would pick up a false positive on row 5. This risk won't always exist, and would depend on the configuration of your data.*
Example:
Assuming your data is in columns B:G. Make H1 equal to the following formula, and drag down:
=B1&C1&D1&E1&F1&G1
Then your formula, assuming your search term is "foobar", would be as follows:
=INDEX(A:A,MATCH("*foobar*",H:H,0))
Assuming your search term is found in cell I1, the formula would be:
=INDEX(A:A,MATCH("*"&I1&"*",H:H,0))
*As pointed out in the comments below, to avoid picking up 'junk', you could insert data guaranteed not to be present in your search terms, in order to avoid a false positive. For example, the formula in column H could be adjusted to:
=B1&"|"&C1&"|"&D1&"|"&E1&"|"&F1&"|"&G1
Note that because the 'pipe' symbol would not be in your data [if it would, insert your preferred 'special' symbol(s) instead], any search term which starts in the middle of B1 and is continued at the beginning of C1 would not create a false positive.

How to search a range for multiple pieces of text

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.

Resources