I am trying to count the unique values of a column, based on their status in another column, example:
Customers
License Active
Adam
Yes
Barry
No
Adam
No
Claire
No
In this situation, I want to know how many customers have at least 1 active license, and how many customers do not have at least one active license.
The formula I have tried is:
=COUNTUNIQUEIFS(A2:A,B2:B,"Yes")
This returns 1 in this situation which is correct, as there is 1 customer who has a Yes on column B.
My issue is when I try to do the reverse, count the "No" using this formula:
=COUNTUNIQUEIFS(A2:A,B2:B,"No") it returns 3 which is not the desired result as it is counting the second Adam as a unique value too because they have a "No" in column B.
The result I want here is 2, because Adam has a yes somewhere in column B so I don't want him counted again the next time his field is counted.
It seems to me that the easiest way to get the "No" count is like this:
=COUNTUNIQUE(A2:A)-COUNTUNIQUEIFS(A2:A,B2:B,"Yes")
It's even easier if you've already pulled the "Yes" count to a cell (say, C2), in which case the "No" count could be gained quite simply with this:
=COUNTUNIQUE(A2:A)-C2
I don't think you can do it in a single step - try filtering out those with at least one "Yes" like this:
=countunique(filter(A2:A,countifs(B2:B,"Yes",A2:A,A2:A)=0))
Explanation
When a countifs has a range instead of a single value in its criteria part countifs(B2:B,"Yes",A2:A,A2:A) , the countifs gets re-evaluated for each cell in the range. So you get an array with the results of
countifs(B2:B,"Yes",A2:A,A2)
countifs(B2:B,"Yes",A2:A,A3)
countifs(B2:B,"Yes",A2:A,A4)
countifs(B2:B,"Yes",A2:A,A5)
and so on all the way down the columns.
The first countifs above checks right through a2:a and b2:b to see if there are any cases where the name is Adam and the license condition is true and gets a count of 1 so that row is filtered out. The same thing happens in the next row containing Adam (row 4) - the countifs checks right through both columns excluding the headers and the count is still 1 so that row is filtered out as well leaving just Barry and Claire.
If you wanted to exclude all records containing "Test" in the Customer column, You could add a condition to the filter using the multiplication operator to 'AND' it with the existing condition:
=countunique(filter(A2:A,(countifs(B2:B,"Yes",A2:A,A2:A)=0)*(A2:A<>"Test")))
If you had several names to exclude, you would probably want to make a list of them and use a lookup to stop the formula getting too long and unwieldy, but it would be the same idea.
Related
Editable Test Sheet:
https://docs.google.com/spreadsheets/d/1zKtE09TB-mAEQFRswity3R1ZGdYe7jq6ZYh_l4P398E/edit?usp=sharing
Although I believe what I'm trying to do is fairly simple, It is difficult for me to even find the correct words to describe what I'm trying to do. I suspect that is why I've been researching all day for an answer and cannot find it.
I need an ARRAYFORMULA that can check for the existence of a given "PARENT ID" in another table, but only if another cell in the same row is not true.
A given PARENT ID from TABLE 2 could appear in TABLE 1 multiple times, sometimes paired with "TRUE" and sometimes not. I only need to know if the PARENT ID from TABLE 1 appears in TABLE 2 along with the value TRUE in the "Done" column next to it. If it appears even once, I want to denote it in TABLE 2.
I am able to do this in various forms, but none of them work with ARRAYFORMULA.
See the shared example sheet above. I would greatly appreciate any help.
See my two newly added sheets ("Erik Help" and "Erik Help 2"). Below are the formulas I used:
In "Erik Help":
=ArrayFormula({"In Table 1 and Not Done?";IF(E3:E="",,IF(ISERROR(VLOOKUP(E3:E,TRIM(B3:B&C3:C),1,FALSE)),,TRUE))})
This delivers the results you want as asked (though your manually entered results did not list F3 as TRUE when I believe it should be).
The trick here is looking for the Parent ID within a virtual column that concatenates Col B and Col C and then TRIMs out extra characters (such as null). If there is an exact match, we know that there was no value in Col B. And since the only valid Col-B value is Boolean TRUE, we are assured that any match is in effect false (or not Done).
In "Erik Help 2":
=ArrayFormula({"In Table 1 and Not Done?";IF(E3:E="",,IF(ISERROR(VLOOKUP(E3:E,TRIM(B3:B&C3:C),1,FALSE)),,IFERROR("Item ID(s): "&VLOOKUP(E3:E,REGEXREPLACE(TRIM(SPLIT(FLATTEN(QUERY(QUERY({FILTER(C3:C,A3:A<>"",B3:B<>TRUE)&"~",FILTER(A3:A&" (R"&ROW(A3:A)&")",A3:A<>"",B3:B<>TRUE)&","}, "Select MAX(Col2) GROUP BY Col2 PIVOT Col1"),, 9^9)),"~")),"[,\s]+$",""),2,FALSE),TRUE)))})
Instead of simply TRUE, this version returns the Item ID(s) that are not done for that Parent ID along with the row number where each incomplete Item ID is found.
Since you didn't expressly ask for this, I'm considering it bonus material and will not take time to explain it.
Another answer I received on another forum:
=ArrayFormula(IF(COUNTIF(C3:C&B3:B,E3:E),true,))
Credit to Prashanth KV
i'm confused with the following condition, simply i want to have arrayformula or maybe a custom-formula to increment number in a way bound by specific condition based on value in other column, put it simply :
if the group doesn't change and sub-group is different increment number by 1
else if the group doesn't change and sub-group is doesn't change (same) hold value by previous
else if the group change regardless sub-group value reset number back to 1
for ilustration
** notes Number is the result that i want, in example i fill it manually
Group
Sub-Group
Animal
Number
Land
poisonus
snake
1
land
friendly
dog
2
land
friendly
cat
2
land
scary
lion
3
aquatic
friendly
nemo fish
1
aquatic
predator
shark
2
UPDATE (dummy file link) :
https://docs.google.com/spreadsheets/d/1DAPf-DvWz50_DJ0IqAoSHbfEnfg_mN1lNXHcCjkj27M/edit#gid=0
try:
=INDEX(IF(A4:A="",,VLOOKUP(A4:A&B4:B, {UNIQUE(A4:A&B4:B), COUNTIFS(
REGEXEXTRACT(UNIQUE(A4:A&"×"&B4:B), "(.*)×"),
REGEXEXTRACT(UNIQUE(A4:A&"×"&B4:B), "(.*)×"),
SEQUENCE(COUNTA(UNIQUE(A4:A&"×"&B4:B))), "<="&
SEQUENCE(COUNTA(UNIQUE(A4:A&"×"&B4:B))))}, 2, 0)))
I have entered my solution in cell D1 of the sheet "Erik Help." As I said in the comments to your original post, this is a more complex solution than I can generally offer here on the free, volunteer-run forums. I did choose to develop and share the formula with you, but I will need to leave it to you (and any other future site visitors who may be interested) to study the formula for understanding how it works. Explaining the formula would take longer than writing it.
Here is the formula:
=ArrayFormula({"Number"; IF(A2:A="",,VLOOKUP(LOWER(A2:A&B2:B),QUERY({UNIQUE(FILTER({A2:B,A2:A&B2:B},A2:A<>"")),COUNTIFS(QUERY(UNIQUE(FILTER({A2:B,A2:A&B2:B},A2:A<>"")),"Select Col1"),QUERY(UNIQUE(FILTER({A2:B,A2:A&B2:B},A2:A<>"")),"Select Col1"),SEQUENCE(COUNTA(QUERY(UNIQUE(FILTER({A2:B,A2:A&B2:B},A2:A<>"")),"Select Col1"))),"<="&SEQUENCE(COUNTA(QUERY(UNIQUE(FILTER({A2:B,A2:A&B2:B},A2:A<>"")),"Select Col1"))))},"Select Col3, Col4"),2,FALSE))})
Image of formula not working
I am trying to filter data by column reference
Not Work For Me =UNIQUE(A2:C6)
What i want it shoutd be like What actually i want
I want find UNIQUE Data Through Column Reference B is Mo No.
Solution
In this case a simple UNIQUE statement is not enough. You are looking for a function that takes in account only one column for your uniqueness check.
In this case SORTN is best suited for this job.
=SORTN(A1:C7,7,2,2,1)
Here is how it works:
n: The number of items to return. Must be greater than 0.
I have 7 rows so at most 7 results
display_ties_mode: A number representing the way to display ties.
In this case 2: Show at most the first n(7) rows after removing duplicate rows.
sort_column1: The index of the column in range or a range outside of range containing the values to sort by.
In this case is 2 as well. Since the uniqueness check is performed in the B Column.
is_ascending: TRUE or FALSE indicating whether to sort sort_column in ascending order.
This is up to you
My table contains 2 sheets with a different number of columns. I want to add a column that will display true or false (or any other 2 opposite values ) for each row depending on whether this row satisfies 2 criteria which are: sheet1!col1=sheet2!col1 and sheet1!col2=sheet2!col2.
You'll find an illustration below.
I've tried using
ARRAYFORMULA(VLOOKUP(A1&B1, {Sheet1!A1:A4&Sheet1!B1:B4,Sheet1!C1}, 3))
but I get an error message
vlookup evaluates to an out of bound range
So I wanted to try
QUERY({Sheet1!A1:B4,A1:B5}, "Select C where ")
but I couldn't figure out how to write the condition where (sheet1)col1=(sheet2)col1 & (sheet1)col2=(sheet2)col2 and I also don't know if I can work with tables of different dimensions. I finally tried
=MATCH(A1&B1,{Sheet1!A1:A&Sheet1!B1:B})
but it always returns 1.
Any idea please?
Sheet 1
Sheet 2
Your first formula is almost right. You are getting the error message because there is only one column in the curly brackets so you have to change it to
=ArrayFormula(vlookup(A1&B1,{Sheet2!A:A&Sheet2!B:B},1,false))
and add the 'false' to make sure it only does exact matches.
To make the query work you need the right syntax to access cells in the current sheet:
=query(Sheet2!A:B," select A,B where A='"&A1&"' and B='"&B1&"'")
To make the match work, you need to enter it as an array formula and add a zero to specify exact match:
=ArrayFormula(MATCH(A1&B1,{Sheet2!A:A&Sheet2!B:B},0))
However I would take flak from my colleagues if I didn't point out that there is an issue with the vlookup and match as shown above - toto&moto would match with not just toto&moto, but also with tot&omoto etc. The way round this is to add a separator character e.g.
=ArrayFormula(vlookup(A1&"|"&B1,{Sheet2!A:A&"|"&Sheet2!B:B},1,false))
=ArrayFormula(MATCH(A1&"|"&B1,{Sheet2!A:A&"|"&Sheet2!B:B},0))
These still need some tidying up if they are to report Yes and No, and also not to give false positive on blank rows - also the vlookup and match can be written as self-expanding array formulas - but that is the short answer to the question.
I have a spreadsheet where I have data from a bank account. Each bank transaction has a date and an indication if that transaction is already done or if it's just expected. When it's already done, it must be added to the total balance up to date. If not, then the total balance up to date must be blank. I need to autofilter the data, so I can filter and order it depending on date or other conditions, that's why I've been using this formula:
=IF(D3="Y";B3+INDIRECT(ADDRESS(ROW()-1;COLUMN()));"")
Problem here is that when the cell above is blank, total sum resets and it starts from the value of that transaction. I need a formula that ignores the upper blank cells, and sums all cells above that are not blank plus the amount of that transaction.
Besides, once I change the "N" in "Done" Column to a "Y" I need the formula to update and show the correct balance.
I share an example sheet for better understanding https://docs.google.com/spreadsheets/d/1_gk0YaziUhOZfRbrlfHizMrVu6OT7njIaTUyQaE6Lbs/edit?usp=sharing
Ok I THINK I understand what your going for - please let me know if I am confused, but I added an example on your sheet.... basically what I ended up doing was including one of your conditionals, but then also adding another function to exclude the blank rows by way of filter , index and counta It looks more complicated than it is because I nested it all back into one formula:
=IF(I3="Y";sum(G3;index(filter(indirect("F2:"&address(row()-1;column();4));ISNUMBER(indirect("F2:"&address(row()-1;column();4))));counta(filter(indirect("F2:"&address(row()-1;column();4));ISNUMBER(indirect("F2:"&address(row()-1;column();4)))))););)
To work it from the inside out - the way I am excluding the blank rows is by using FILTER to get all the rows from the first row with a value ( Like A2 in your example) and using INDIRECT and ADDRESS to end the array I want to include exactly one cell above the current cell.
Then I use the condition that the range I built has a number value in it, there fore excluding the blanks.
In order to get the last value available, I use COUNTA to find out the total rows in the filter, then wrap the formula with INDEX to use the counta value as the row to return (which automatically is the last row available above the current cell)
Try this in A3 and copy down:
=IF(D3="Y";B3+INDIRECT(ADDRESS(ROW()-1;COLUMN()));A2+0)
If you want to display the "N" rows as blank, add a column (B) fill in the header and the starting number (5000) then put this in B3:
=if(E3="N";"";A3)
Copy it down then hide column A.