COUNTIFS with AND & OR, Including < and > Operators - excel

Column A contains dates. Column B contains dates and text values.
I'd like to write a formula that counts everything where (A:A <= DATE) AND (B:B > DATE OR B:B = "TextValue")
I know you can incorporate OR into countif using a formula like SUM(COUNTIF(A:A,{value1, value2})), but I have too many date values and want to use the > operator in the OR part.
I know this is a weird one with dates and text in the same column. Any help is appreicated.

I assume you want to count the number of rows that satisfy all the logical condition: A AND (C OR D), where each letter represents a logical condition. You can use in G2 the following:
=SUMPRODUCT( --(B2:B5<=E2),
--((--(C2:C5 > E2) + (--(C2:C5 = DATEVALUE(E4)))) > 0) )
or using LET function to represent better each conditions:
=LET(cond1, --(B2:B5 <= E2), cond2, --(C2:C5 > E2),
cond3, --(C2:C5 = DATEVALUE(E4)),
SUMPRODUCT(cond1, --((cond2 + cond3) > 0))
)
Here is the output:
The first row satisfies cond1, and the last row satisfies cond3.
Since you indicated the last condition is against a text value (E4) we need to convert it to a date using DATEVALUE.
SUMPRODUCT is expecting numeric values, so each logical condition needs to be converted to 1,0 values via --() operator. The OR condition is establish as a sum of two binary values and it should be greater than 0.
You can not use COUNTIFS in a scenario like this, because each criteria represents a simple comparison condition such as: "<="&E2 (for cond1 for example) internally it checks the condition: B2:B5 <= E2, i.e. a single logical condition where the left hand side appears only once. For an OR condition you need two logical conditions (i.e. OR(rng < a, rng > b)). In order to count a row all the conditions must be satisfied (logical AND), so there is no way to consider an OR condition with this function.

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.

Filter an excel range based on multiple dynamic filter conditions (with column values delimited)

I posted a similar question: Filter an excel range based on multiple dynamic filter conditions. Now I am considering a more general case, i.e. for one of the filter column (Releases, column E) it may have several values delimited by comma. The expected result should filter by rows that have as release values: A or B, but the releases column can come with more than one value and for team filter by specific one or all of them (ALL wildcard).
Here is the sample (when we have a maximum of two values for releases column):
I was able to obtain the desired result based on filter conditions, but it requires helper columns (columns: J,K,L), via the formula in N3:
=FILTER(D3:H15, (IF(B3="ALL", D3:D15<>"*",D3:D15=B3)) * (L3:L15))
and column L does the magic to identify the rows with the wanted release values:
=LET(result, ISNUMBER(MATCH(J3:K15,TEXTSPLIT(B4,", "),0)), IF((FILTER(result, {1,0})
+ FILTER(result, {0,1}))>0, TRUE, FALSE))
I am looking for a solution that wouldn't require helper columns and also for the general case where Release column can have more than two values, for example: A, C, G, F... if that is possible.
Here a link to my sample file:
https://1drv.ms/x/s!AlZxw2GG3C7Ihyyx8_AM5ylbZWaI?e=F3WUep
Note:
I cannot use TEXTSPLITin a single invocation to obtain columns J,K, because when the text input argument is an array (range) there is no way to delimit by empty string, so TEXTSPLIT(E3:E15,",") doesn't return two columns (it works for a single cell, but not for a range), so I have to use TEXTAFTER(E3:E15,",") to obtain the information after the comma in column K
Lets try-
=FILTER(D3:H15,BYROW(E3:E15,
LAMBDA(x,MAX(--ISNUMBER(XMATCH(TOCOL(TEXTSPLIT(x,",")),
TOCOL(TEXTSPLIT(B4,", ")),0)))))
* IF(B3="ALL",D3:D15<>"",D3:D15=B3))
Explanation of the solution to identify if release value is present:
It uses BYROW function which processes each row by a LAMBDA function you define.
The formula: TOCOL(TEXTSPLIT(B4,", ")
Generates a column array with the values of B4, i.e.: {A;B}(semicolon represents a column array) in our case a 2x1 array. TEXTSPLIT spits a string by delimiter (", ").
The formula: TOCOL(TEXTSPLIT(x,", "))
Generates an array column for a value represented by x split by the delimiter (", ") . For example if x is: A it will generate: {A} and for A,C the output will be: {A;C}, i.e 2x1 array.
The XMATCH function with signature: XMATCH(lookup_value, lookup_array, 0)
will return the index position of lookup_array when an exact match is found for look_value, otherwise N/A. If lookup_value is a column array, the XMATCH function is evaluated for each element of the array and return the result in a column array.
For lookup_array: {A;B} it will produce the following output, based on the following input values:
Lookup_value
Result
{A}
{1}
{A;C}
{1;N/A}
{C;D}
{N/A;N/A}
{A;B}
{1;2}
{B;A}
{2;1}
{B;A;C}
{2;1;N/A}
{C}
{N/A}
In our case:
XMATCH(TOCOL(TEXTSPLIT(x,", ")),TOCOL(TEXTSPLIT(B4,", ")),0)
will return for each releases value (x) ({A}, {A;B}, {A;C}, etc.) a column array of size of the number or elements of x, indicating the row position of {A, B} (if matches) or N/A (not found) for each element of x.
ISNUMBER converts the result to TRUE (if matches) or FALSE (for N/A). --ISNUMBER(cell) converts the result to 1 (match) or 0 (for N/A). Finally MAX function returns 1 if there is at least one match, otherwise 0.
Because BYROW processes the LAMBDA function for each row, it returns 1 (at least one match) or 0 (no match) for each row of E3:E15.
=BYROW(E3:E15,LAMBDA(x,
MAX(--ISNUMBER(XMATCH(TOCOL(TEXTSPLIT(x,", ")),
TOCOL(TEXTSPLIT(B4,", ")),0)))))
which is what we need as a filter condition
Note: You can use MATCH function instead of XMATCH, but keep in mind that for the third input argument the default behavior is different. The default value for MATCH is 1 (largest value that is less than or equal to lookup_value) and for XMATCH is 0 (exact match).

How to count certain texts coming from VLOOKUP function?

I want to count a certain type with a certain step.
For instance, I want to count Type A and Step 1 with =COUNTIFS(A:A,"A",B:B,"Step 1").
However, Steps from Column B come from VLOOKUP function that fetches from different Excel file: for instance, =IFERROR(VLOOKUP($AC9,'Sheet X'!$B$1:$Y$893,21,FALSE),""). Is there a way to count a certain text that comes from VLOOKUP?
I prefer the double unary operator for counting instances like this, it allows you to easily combine as many conditions like this as you like:
=sumproduct(--($A$1:$A$893 = "A", $B$1:$B$893 = "Step 1"))
You can add more conditions by addint commas within the --() section of the sumproduct. What this does is force each column to a one/zero array of the condition (1 if = "A") and multiplies them together, so only if all conditions are true / 1, they'll be counted. In this instance the function will return the value 2, as both are true only for two rows.
If the values in the steps column come from a vlookup, it would not affect this function, as it is just using the values in the cell shown.

Multiple Or Conditions in a Countifs Statement

Is it possible to have multiple OR conditions in a countifs statement?
I am trying to write a statement that counts the number of records where the relationship is either 'Contractor' OR 'Supplier' AND if the Severity is either 'Serious' OR Major. The first OR condition will work, but only the first condition in the second OR statement is being picked up. Here is what i have written:
=(COUNTIFS(Data!F:F,{"Contractor","Supplier"},Data!E:E,{"Serious","Major"}))
=SUMPRODUCT((Data!F:F="Contractor")+(Data!F:F="Supplier"),(Data!E:E="Serious")+(Data!E:E="Major"))
The (Data!F:F="Contractor") will produce an array of TRUE/FALSE the size of column F, with TRUE only where Column F is "Contractor".
The (Data!F:F="Supplier") will produce an array of TRUE/FALSE the size of column F, with TRUE only where Column F is "Supplier".
the above two arrays are "ADDED" - this converts them to 1/0s instead and adds the two arrays together, producing an array the size of column F, with 1 / 0 s, with 1s where cells in column F are EITHER "Contractor" or "Supplier".
the same for "Serious"/"Major"
inside the SUMPRODUCT the two arrays with 1&0s are MULTIPLIED together, so will return a 1 ONLY when there is a 1 in BOTH arrays so: F is {"Contractor OR "Supplier"} AND E is {"Serious" OR "Major"}
the whole array is then summed (by the SUMPRODUCT() ) to return the COUNT of rows that match the criteria (as a single number)

Compare two sheets as matrix table

A1:200 B1:260
A2:300 B2:220
A3:400 B3:240
A4:200 B4:300
A5:200 B5:200
I got two tables going on and basically I want to check if row A is greater than 200 AND row B is greater than 250 then count.
So far I have this:
=COUNTIF(A1:A5,">= 200")
but I have no idea how to check if A passes then check B and if so, count it. I'm guessing something to do with IF, AND and maybe a for loop? I'm not familiar with this language at all :x
You want to calculate total count when column A is greater than 200 and B contains cell values greater than 250.
If you want a single value for entire table use countifs,
=COUNTIFS($A$1:$A$5,">200",$B$1:$B$5,">250")
If you want to get the counts in different column (let say C) on each row, then copy and paste below formula in C1 and drag it to C5 cell
=+IF(AND(A1>200,B1>250),1,0)
Where 1 means both conditions are true and 0 means either of condition is false.
However if you want to check first if the first condition is satisfying or not, then you can use below formula:
=+IF(A1>200,IF(B1>250,1,0),2)
Where "1" means true and both the condtion is satisfying , "0" means first condition is satisfying but second is not and "2" means the first condition is not satisfying hence it didn't check the second condition.
Hope this helps

Resources