I've been searching for several hours for what I thought would be a pretty straight forward problem but without any luck.
I need an array formula (needs to calculate for range without copying down the formula) that returns an index reference to the column containing a match for the passed criteria for each row. I don't need the value returned, which is what I've seen related problems solving for, just the column index. I will be using the returned index value to pull data from a bound matrix containing data such as allocated hours. I tried to use MATCH inside an ArrayFormula with a dynamic index for the lookup range but it doesn't increment the row as I would expect. Below is example data with the desired results shown in the first column (technically the results will be returned in a separate worksheet but included here for illustrative purposes), assignee is the criteria for which to find the matching column index across reviewers 1 - 3.
+---------+----------+------------+------------+------------+
| Results | Assignee | Reviewer 1 | Reviewer 2 | Reviewer 3 |
+---------+----------+------------+------------+------------+
| 2 | Paul | Tim | Paul | Sue |
| 1 | Nick | Nick | Linda | Adam |
| 3 | Bill | Ryan | Paul | Bill |
| 2 | Tom | Paul | Tom | Sarah |
+---------+----------+------------+------------+------------+
I've been struggling with this for a while so any guidance would be appreciated!
Try this:
=MMULT(ARRAYFORMULA(--('Table 2'!A3:D7) * --('Table 1'!A3:A7 = 'Table 1'!B3:E7)), SEQUENCE(COLUMNS('Table 1'!B3:E7), 1, 1, 0))
--('Table 2'!A3:D7) - places 0s instead of blanks in table 2 (needed for MMULT).
--('Table 1'!A3:A7 = 'Table 1'!B3:E7) - gives a table with 1s in cells corresponding to current reviewer, and 0s in all the other.
Then those two ranges are multiplied cell by cell. That gives a table with the right hours in cells with the reviewers' names, one value in a row.
MMULT gives a row wise sum, which is effectively a column of those hours from the previous step.
If you'll have a bigger table you'll just need to adjust Table 1'!A3:A7, 'Table 1'!B3:E7, and Table 2'!A3:D7 accordingly. The rest will remain the same.
The best I've been able to come up with so far is this SWITCH statement. It works but not so elegant
=ArrayFormula(SWITCH(Current_Assignee, INDEX(Queue,,1), "1", INDEX(Queue,,2), "2", INDEX(Queue,,3), "3", INDEX(Queue,,4), "4", INDEX(Queue,,5), "5"))
I have a table like:
| 1 | 10 | <unique appearences from A&B>
| 2 | 10 | <unique appearences from A&B>
| 1 | 20 | <unique appearences from A&B>
| ... |
I want to use a fixed area (columns A:B) and count how much this combination of A & B appeared before including current row.
I use this formula: =ARRAYFORMULA(IF(A2:A<>"";COUNTIFS(A$2:A;A2:A;B$2:B;B2:B);"")).
Each row with its own formula is working: (for row A): =COUNTIFS(A$2:A2;A2;B$2:B2;B2).
Here my example sheet.
Is it possible to make an area in an array formula as fixed?
For specific fields does INDIRECT() sometimes help but not for arrays.
$ doesn't help either.
I mean I figured already out that some functions don't work with array formula like JOIN() - is this also such a case?
=ARRAYFORMULA(COUNTIFS(A2:A21&B2:B21,A2:A21&B2:B21,ROW(A2:A21),"<="&ROW(A2:A21)))
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.
Given a set of multi-dimensional data represented in a Google Spreadsheet:
A | 1 | x
A | 2 | y
A | 3 | z
It is pretty straightforward to do a lookup on multiple values using the FILTER and INDEX functions. Doing a lookup for A2 would result in y. However, if the similar data is merged into a single cell:
| 1 | x
A | 2 | y
| 3 | z
Is there a function that would accomplish the same thing? the FILTER method only returns the first row in the implicit set because there is only an A actually on the first row.
If interested, you can view the live sheet here using the 'Rules' sheet.
I have been working on a custom function, but am hoping for something more portable. Helper cells would be fine, as long as I can hide them on a separate sheet.
One option, using the helper cells idea, would be to "normalise" your Rules sheet on a separate (hidden) sheet, and perform lookups on that sheet. Eg, in A3 of that sheet:
=ArrayFormula(HLOOKUP(IF(ROW(Rules!A3:A),Rules!A2),Rules!A2:A,VLOOKUP(ROW(Rules!A3:A),FILTER(ROW(Rules!A3:A),LEN(Rules!A3:A)),1)-1,0))
and fill that formula across to the right as far as required. Note: this formula will only work on the new version of Sheets (which you are using).
What I want is to easily multiply a number by another number for each column and add them up at the end in Google Sheets. For example:
User | Points 1 | Points 2 | Points 3 | Total
| 5 | 1 | 4 |
-----+----------+----------+----------+------
Jane | 2 | 3 | 0 | 13 (2*5 + 3*1 + 0*4)
John | 1 | 11 | 4 | 32 (1*5 + 11*1 + 4*4)
So it's easy enough to make this formula for the total:
= B3*$B$2 + C3*$C$2 + D3*$D$2
The problem is I frequently need to insert additional columns or even remove some columns. So then I have to mess with all the formulas. It's a pain... we have many spreadsheets with these formulas. I wish there was a formula like SUM(B3:D3) where I could just specify a range. Is there anything like MULTIPLY_AND_SUM(B2:D2, B3:D3) that would do this? Then I could insert columns in the middle and the range would still work.
There is a built in function in Google Sheets that does exactly what you are looking for: SUMPRODUCT.
In your example the formula would be:
=sumproduct(B$2:D$2,B3:D3)
Click here for more information about this function.
You can accomplish that without requiring a special-purpose function.
In E3, try this (and copy it to the rest of your rows):
=sum(arrayformula(B3:D3*B$2:D$2))
You can read about arrayformula here.
As long as you introduce new columns between B and D, this formula will automatically adjust. If you add new columns outside of that range, you'll need to edit (and cut & paste).
On it's own, arrayformula(B3:D3*B$2:D$2) operates over each value in B3:D3 in turn, multiplying it by the corresponding value in B$2:D$2. (Note the use of absolute references to 'lock down' to row 2.) The result in this case is three values, [10,3,0], arranged horizontally in three rows because that matches the dimensions of the ranges.
The enveloping sum() function adds up the values of the array produced by arrayformula, which is 13 in this case.
As you copy that formula to other rows, the relative range references get updated for the new row.