In a Google Spreadsheet: How can I count the rows of a given area that have a value? All hints about this I found up to now lead to formulas that do count the rows which have a not empty content (including formula), but a cell with
=IF(1=2;"";"") // Shows an empty cell
is counted as well.
What is the solution to this simple task?
I just used =COUNTIF(Range, "<>") and it counted non-empty cells for me.
=counta(range)
counta: "Returns a count of the number of values in a dataset"
Note: CountA considers "" to be a value. Only cells that are blank (press delete in a cell to blank it) are not counted.
Google support: https://support.google.com/docs/answer/3093991
countblank: "Returns the number of empty cells in a given range"
Note: CountBlank considers both blank cells (press delete to blank a cell) and cells that have a formula that returns "" to be empty cells.
Google Support: https://support.google.com/docs/answer/3093403
If you have a range that includes formulae that result in "", then you can modify your formula from
=counta(range)
to:
=Counta(range) - Countblank(range)
EDIT: the function is countblank, not countblanks, the latter will give an error.
Here's what I believe is the best solution so far:
=CountIf(ArrayFormula(range<>""),TRUE)
Here's why in 3 easy steps
Step 1: Simple As Pie - Add Extra Column
The answer by eniacAvenger will yield the correct solution without worrying about edge cases as =A1<>"" seems to arrive at the correct truthy/falsy value based on how we intuitively think of blank cells, either virgin blanks or created blanks.
So imagine we have this data and we want the Count of non-blanks in B2:B6:
| | A | B | C |
|---|-------------|-------|---------|
| 1 | Description | Value | B1<>"" |
| 2 | Text | H | TRUE |
| 3 | Number | 1 | TRUE |
| 4 | IF -> "" | | FALSE |
| 5 | IF -> Text | h | TRUE |
| 6 | Blank | | FALSE |
If we relied on Column C, we could get the count of values in B like this:
=COUNTIF(C2:C6,True)
Step 2: Use FormulaArray to dynamically create Extra Column
However, consideRatio's comment is a valid one - if you need an extra column, you can often accomplish the same goal with an ArrayFormula which can create a column in memory without eating up sheet space.
So if we want to create C dynamically, we can use an array formula like this:
=ArrayFormula(B2:B6<>"")
If we simply put it in C2, it would create the vertical array with a single stroke of the pen:
| | A | B | C |
|---|-------------|-------|--------------------------|
| 1 | Description | Value | =ArrayFormula(B2:B6<>"") |
| 2 | Text | H | TRUE |
| 3 | Number | 1 | TRUE |
| 4 | IF -> "" | | FALSE |
| 5 | IF -> Text | h | TRUE |
| 6 | Blank | | FALSE |
Step 3: Count Values in Dynamic Column
But with that solved, we no longer need the column to merely display the values.
ArrayFormula will resolve to the following range: {True,True,False,True,False}.
CountIf just takes in any range and in this case can count the number of True values.
So we can wrap CountIf around the values produced by ArrayFormula like this:
=CountIf(ArrayFormula(B2:B6<>""),TRUE)
Further Reading
The other solutions in this thread are either overly complex, or fail in particular edge cases that I've enumerated in this test sheet:
Google Spreadsheet - CountA Test - Demo
For why CountA works the wonky way it does, see my answer here
For me, none of the answers worked for ranges that include both virgin cells and cells that are empty based on a formula (e.g. =IF(1=2;"";""))
What solved it for me is this:
=COUNTA(FILTER(range, range <> ""))
It works for me:
=SUMPRODUCT(NOT(ISBLANK(F2:F)))
Count of all non-empty cells from F2 to the end of the column
Solved using a solution i found googling by Yogi Anand: https://productforums.google.com/d/msg/docs/3qsR2m-1Xx8/sSU6Z6NYLOcJ
The example below counts the number of non-empty rows in the range A3:C, remember to update both ranges in the formula with your range of interest.
=ArrayFormula(SUM(SIGN(MMULT(LEN(A3:C), TRANSPOSE(SIGN(COLUMN(A3:C)))))))
Also make sure to avoid circular dependencies, it will happen if you for example count the number of non-empty rows in A:C and place this formula in the A or C column.
Given the range A:A, Id suggest:
=COUNTA(A:A)-(COUNTIF(A:A,"*")-COUNTIF(A:A,"?*"))
The problem is COUNTA over-counts by exactly the number of cells with zero length strings "".
The solution is to find a count of exactly these cells. This can be found by looking for all text cells and subtracting all text cells with at least one character
COUNTA(A:A): cells with value, including "" but excluding truly empty cells
COUNTIF(A:A,"*"): cells recognized as text, including "" but excluding truly blank cells
COUNTIF(A:A,"?*"): cells recognized as text with at least one character
This means that the value COUNTIF(A:A,"*")-COUNTIF(A:A,"?*") should be the number of text cells minus the number of text cells that have at least one character i.e. the count of cells containing exactly ""
A simpler solution that works for me:
=COUNTIFS(A:A;"<>"&"")
It counts both numbers, strings, dates, etc that are not empty
As far as I can see, most of the solutions here count the number of non empty cells, and not the number of rows with non empty cell inside.
One possible solution for the range B3:E29 is for example
=SUM(ArrayFormula(IF(B3:B29&C3:C29&D3:D29&E3:E29="";0;1)))
Here ArrayFormula(IF(B3:B29&C3:C29&D3:D29&E3:E29="";0;1)) returns a column of 0 (if the row is empty) and 1 (else).
Another one is given in consideRatio's answer.
You can define a custom function using Apps Script (Tools > Script editor) called for example numNonEmptyRows :
function numNonEmptyRows(range) {
Logger.log("inside");
Logger.log(range);
if (range && range.constructor === Array) {
return range.map(function(a){return a.join('')}).filter(Boolean).length
}
else {
return range ? 1 : 0;
}
}
And then use it in a cell like this =numNonEmptyRows(A23:C25) to count the number of non empty rows in the range A23:C25;
In Google Sheets, to count the number of rows which contain at least one non-empty cell within a two-dimensional range:
=ARRAYFORMULA(
SUM(
N(
MMULT(
N(A1:C5<>""),
TRANSPOSE(COLUMN(A1:C5)^0)
)
>0
)
)
)
Where A1:C5 is the range you're checking for non-empty rows.
The formula comes from, and is explained in the following article from EXCELXOR - https://excelxor.com/2015/03/30/counting-rows-where-at-least-one-condition-is-met/
A very flexible way to do that kind of things is using ARRAYFORMULA.
As an example imagine you want to count non empty strings (text fields) you can use this code:
=ARRAYFORMULA(SUM(IF(Len(B3:B14)>0, 1, 0)))
What happens here is that "ArrayFormula" let you operate over a set of values. Using the SUM function you indicates "ArrayFormula" to sum any value of the set. The "If" clause is only used to check "empty" or "not empty", 1 for not empty and 0 otherwise. "Len" returns the length of the different text fields, there is where you define the set (range) you want to check. Finally "ArrayFormula" will sum 1 for each field inside the set(range) in which "len" returns more than 0.
If you want to check any other condition, just modify the first argument of the IF clause.
Make another column that determines if the referenced cell is blank using the function "CountBlank". Then use count on the values created in the new "CountBlank" column.
Related
I'm still new to Google Sheets and still learning, so in my GS I tried using AND and OR formula to produce the results like: -
A | B
-----
1 | 1 TRUE
1 | 2 TRUE
2 | 1 TRUE
2 | 2 FALSE
3 | 1 FALSE
3 | 2 FALSE
But this is the closest I get. What is the best formula that will help me produce result like I shown above.
Your rule is not entirely clear. For instance, could there be zero values? Negative values? But since you have not included such examples in your sample set, the following formula will produce the desired result according to the only data you've included.
Assuming you have headers in A1 and B1 and that your numeric data runs A2:B, delete everything from Col C (including any header) and place the following formula in C1:
=ArrayFormula({"Header";IF(A2:A="",,A2:A+B2:B<=3)})
This one formula will produce all results for all rows (again, judging by the very small data set and implied rule for such in our post).
You can change Header to any header text you like.
The rest reads this way: "If any cell in A2:A is empty, return null in the corresponding cell of that row in Col C. Otherwise, assess whether the combined total of the numbers in Col A and Col B is less than or equal to 3 and return TRUE or FALSE accordingly."
I created a pivot table in googlesheets, and it returns results that look like:
first | second | CountOf3
--------------------------
thing | value | 23
| newVal | 3
| cool | 34
that | value | 234
otherThing | cool | 4
| newVal | 345
And I want to filter out results with just one resulting row for the item in the first column.
So in this example, that would be the row: that | value | 234.
I would like the filter to remove that row, and leave the remaining rows. This is a pivot table in a 2nd sheet that updates when Sheet1 changes.
I have been trying all day, and have not been able to come up with a solution. I was hoping there would be some sort of filter, or spreadsheet formula to do this. I've tried multiple combinations of filters, but nothing seems to work - I'm starting to wonder if this is even possible.
It isn't pretty, but a brute force way is to have a check column beside your pivot table, with this formula on the first data row, ie beside "thing | value | 23".
It flags each row where the subsequent cell in column D is not blank. Then use a query (or filter) to list only the output rows you want. Note that you would hide the columns or rows with the actual (unfiltered) pivot output.
This is the simplest version, to see the logic:
=AND(LEN(D3),LEN(D4))
which results in a TRUE value for pivot chart rows that only have one value.
A more elegant version is an arrayformula, adds the header lable, and uses "Skip" as the flag for which rows to filter out.
={"Better Check";ARRAYFORMULA(IF(LEN(D3:D998)*LEN(D4:D999)*LEN(E3:E998),"Skip",))}
Note that this formula allows for a pivot table result effectively to the bottom of the sheet, but it does have a finite range, due to the constraint of checking two rows at once. It could be enhanced by using a COUNTA on the third data column to measure the exact length of the pivot table results and control the range dynamically, Like this:
={"Better Check";
ARRAYFORMULA( IF( LEN(INDIRECT("D3:D" & (COUNTA(F$3:F)+ROW(F$2)))) *
LEN(INDIRECT("D4:D" & (COUNTA(F$3:F)+1+ROW(F$2)))),
"Skip",))}
Let us know if this helps at all.
I want to apply conditional formatting so that all the rows which match another row exactly are highlighted.
Let's say I have a spreadsheet like the following
| | a | b | c |
|---|---|---|---|
| 1 | A | B | C | // Matches row 3 and 6
| 2 | A | B | A | // Matches row 5
| 3 | A | B | C | // Matches row 1 and 6
| 4 | B | B | C | // Matches no other row
| 5 | A | B | A | // Matches Row 2
| 6 | A | B | C | // Matches row 1 and 3
| 7 | B | B | A | // Matches no other row
All the rows except for row 4 and 7 would be highlighted.
For to rows to be considered duplicates, the value of each/every cell in a given row must exactly match the value of the corresponding cell (cell in the same column) in a duplicate row.
My attempt so far can only return the values of rows with only the first 2 cells being duplicate and returns the concatenation of all the duplicate values in each row, which is very far away from what I want.
CC = arrayformula(A:A&" "&B:B&" "&C:C) returns a new row which is the concatenation of A, B, and C, which is coercing the cell values into strings so "1" and 1 which are not the same appear to be the same, and also doesn't work across the entire row (could do If I just kept adding Columns, but would look terrible).
=filter(unique(CC), arrayformula(countif(CC, unique(CC)) > 1)) CC is the returned value from the previous equation
This would output
A B C
A B A
Then I could add a conditional formatting rule with a custom formula that Highlights a row if it's concatenated contents "Match" one of the return values from the previous equation, but I don't know how to do that, and the previous equation is already pretty flawed.
Ideally I want a solution that involves no string concatenation or entering in all column names.
Let's go over what is needed to create this function.
1st you need to get the rows as a string to be able to compare them like you did. I didn't use space like you did because it takes place, but you can keep them.
=ARRAYFORMULA(A:A&B:B&C:C)
The issue with that is that since the formula will be on 3 column, we don't want it to become C:C&D:D&E:E so we have to fix the column.
=ARRAYFORMULA($A:$A&$B:$B&$C:$C)
Yay! Now we have a list of string that represent the "value" of each row. We can now count for each line how many times they are found. I used A2 cause I guess you have a header, but if you don't, simply replace it with A1.
=COUNTIF(ARRAYFORMULA($A:$A&$B:$B&$C:$C);A2&B2&C2)
We also have to fix the column here or the function will only work on the 1st one.
=COUNTIF(ARRAYFORMULA($A:$A&$B:$B&$C:$C);$A2&$B2&$C2)
And now all that's left is check if you want to see thoses who are unique or thoses who have matches
=COUNTIF(ARRAYFORMULA($A:$A&$B:$B&$C:$C);$A2&$B2&$C2)>1
This solution doesn't involved converting the values to strings, but it still requires adding a function for every column, so it's almost there.
=countifs(arrayformula($A:$A=$A1),TRUE,arrayformula($B:$B=$B1),TRUE,arrayformula($C:$C=$C1),TRUE)>1
It's just a conditional for each column conditional = arrayformula($A:$A=$A1) in a countifs, countifs(conditional, true).
I just need to make it so it can take the column values as an array which i'm guessing will require an arrayformula
There is a MUCH simpler way.
Load Conditional Formatting (under Format).
Select "custom formula is" (way at the bottom of the formula list)
Use the formula "=countif(A:A,A1)>1", where A is the column that contains the cells you want to be formatted for duplicates.
I am getting this error message on my query formula
"Unable to parse query string for Function QUERY parameter 2:
AVG_SUM_ONLY_NUMERIC"
and I don't know what seems to be the problem. I already change the format of column C to percentage but I'm still getting the same error.
=Query('Sheet1'!A1:C, "select A, avg(C), count(C) group by A,C", 1)
Sample Data:
Date | Name | CSAT %|
-----------|------|-------|
2017-10-22| asdf | 100%|
2017-10-15| qwer | 50% |
2017-10-08| zxcv | 75% |
2017-10-01| qwer | 90% |
One column of numerical data in my sheet would not register as numbers, no matter what (you can test this with function N(). It will show 0 for data which isn't considered numerical).
I fixed this with an extra column which added 0 to my numerical column. Even though the original column wasn't considered numerical, this somehow worked.
I finally solved the puzzle using this:
=arrayformula(query({'Sheet1'!A:N, arrayformula(if(ISBLANK('Sheet1'!O:O), -1, value('Sheet1'!O:O)))
Basically, I put -1 on blank spaces in between rows and then on my query, I placed a condition to include only rows that have a value of >=0.
I need some help figuring out some Google Sheets function. I'm trying to look for the value of an adjacent cell based on a key. The problem is that the table has several rows and columns to search for. For example:
| A | B | C | D |
1 | Alpha | 5 | Bravo | 10 |
2 | Charlie | 15 | Delta | 20 |
The list goes on for several more rows and colums. What I'm looking for for example, is when a search use "Delta" as my search key, it will return the value 20 for me. I appreciate your help. Thanks!
Here is the answer I got on the web application community:
https://webapps.stackexchange.com/questions/90198/how-to-get-value-of-adjacent-cell-based-on-key-if-the-table-is-split-into-multi
You can still use vlookup for this, by stacking the lookup tables into one using the array notation {first ; second; third} which means first above second above third. Example:
=vlookup("Delta", {A:B; C:D}, 2, False)
returns 20.
Try:
=offset(lookup("Delta",A1:D2),0,1)
You could use the following:
=ArrayFormula(INDEX($A$1:$D$2,MIN(IF($A$1:$D$2=$G$1,ROW($A$1:$D$2))),MIN(IF($A$1:$D$2=$G$1,COLUMN($A$1:$D$2)))+1))
This could by done in several ways.
Use RegEx
=regexextract(CONCATENATE(A1:D),F6 & "(\d+)")
where F6 is cell with lookup value i.e. "Delta"
Use lookup
=INDEX(A:D,MATCH(LOOKUP(F6,A1:D,A1:A),A1:A),MATCH(F6,INDIRECT(MATCH(LOOKUP(F6,A1:D,A1:A),A1:A)&":"&MATCH(LOOKUP(F6,A1:D,A1:A),A1:A)))+1)
where F6 is cell with lookup value i.e. "Delta", look at example.
MATCH(LOOKUP(F6,A1:D,A1:A),A1:A) is used 3 times, so it could be counted in separate cell.