Am sorry am unable to paste the table here as my work laptop security doesn't let me.
I have a row with multiple repetitive values eg columnB to BI containing 2s, 3s, 1s, and 3s again.
The value in last column is 3. I want to count for last how many columns was the value 3 before it changed to something else.
For example: if the row looks like
2 2 3 3 3 1 1 2 2 3 3 2 2 2 2 2 , then the answer I want is 5, because the last value is 2 and it was there for last 5 columns.
I hope it makes sense.
Thank you,
Parul.
You can do it by creating a UDF(User Defined Function) in VBA like this one:
Function CountLast(x As Range, y As Integer)
Dim lColumn, count
lColumn = x.Cells(x.count).Column 'Get last column in range x
count = 0
For i = lColumn To 0 Step -1 'Start with last column and work from right to left
If Cells(1, i).Value <> y Then 'Compare value of each cell with the value provided in y and leave the loop if not found
Exit For
End If
count = count + 1 'Counts how many times the value is found
Next i
CountLast = count 'Returns the counted value
End Function
Then you would use it like this:
=CountLast(B1:BI1,BI1)
For the example data that you provide in your question I used:
=CountLast(A1:P1,P1)
and the resulting answer is 5
What is happening is that the UDF is finding the last cell in the range and then starting there is comparing it to the selected value that you also provide the function and working from right to left (step -1) then it counts as long as they match and in the end returns the counted value.
Related
I'm making a document in Google sheets that produces the start and end times where a number of people are in a section. I was able to produce a grid, but I can't seem to find a formula for calculating end times that occur after the start time.
Time
Section1
Section2
9:00am
1
0
9:30am
1
0
10:00am
1
1
10:30am
0
1
I want to make a series of formulas that list the start and end times when people are present in a section.
(Start time) Find the first cell to not contain 0 and return the value in column A {I have found a formula for this step}
(End time) Find the first cell to contain 0 where the row number is greater than the row number of the previous start time and return the value in column A
For the first part, I can find the start time with the formula
=IFNA(INDEX($A$2:$A,(MATCH(TRUE,INDEX($B$2:$B>0,0),0))))
But when I try to adapt it to the end time by changing the greater than (>) to equals (=), it gives me the first time there is a zero regardless of if it occurs before the start time. I feel like adding some kind of row check will be necessary to fix this, but I'm not sure how. I would really rather not learn Google API if at all possible,
If it's just to find the first 0 after a 1, you could benefit from the use of INDEX and MATCH to create a range that goes from the first 1 to the last row and look the 0 in that range. That is: INDEX(B2:B,MATCH(1,B2:B,0)):INDEX(B2:B,ROWS(B2:B)) So, inserted in the whole formula:
=INDEX(A2:A,MATCH(1,B2:B,0) + MATCH(0, INDEX(B2:B,MATCH(1,B2:B,0)):INDEX(B2:B,ROWS(B2:B)) ,0)-1)
this one seems super simple but I'm having a tough time figuring it out, any help would be greatly appreciated.
I have repeating data in Column A, in Column B I need sequential numbering unless the previous row has a repeat value, in which case it would repeat that number in the sequence. Example below.
Is this possible in a single cell array formula?
Column A Column B
7648490 1
7634199 2
7631608 3
7620465 4
7620465 4
7616976 5
7601241 6
7601241 6
7601241 6
7601241 6
7599651 7
7597439 8
7597376 9
7596068 10
7596068 10
7596068 10
7596068 10
7596068 10
7596067 10
Delete everything from Col B (including the header) and place the following formula in B1:
=ArrayFormula({"Header";IF(A2:A="",,VLOOKUP(A2:A,{UNIQUE(FILTER(A2:A,A2:A<>"")),SEQUENCE(COUNTA(UNIQUE(FILTER(A2:A,A2:A<>""))))},2,FALSE))})
This will create header text (which you can change as you like within the formula itself) and will produce the result for each row.
The virtual array formed between the curly brackets { } creates a pairing of each UNIQUE value from Col A with an incremental SEQUENCE that starts at 1. Then VLOOKUP just finds each actual value from Col A within the virtual array and returns the SEQUENCE number.
Looking to convert
Task id
John
Jan
Juliet
1
1
1
0
2
1
0
1
3
0
1
1
4
0
0
1
5
0
1
1
6
1
1
0
7
0
1
0
8
1
0
0
9
0
1
1
10
1
1
0
To
John
Jan
Juliet
John
3
1
Jan
3
3
Juliet
1
3
I have set up a new sheet ("Erik Help") in your sample spreadsheet.
In B1:
=SORT(FILTER(Sheet1!B1:1,Sheet1!B1:1<>""))
This simply fills the top row with your names list, sorted alphabetically.
In A2:
=TRANSPOSE(SORT(FILTER(Sheet1!B1:1,Sheet1!B1:1<>"")))
This fills A2 down with the same names list as above, just vertically.
In B2 is the main formula for the grid (which is then dragged over and down):
=ArrayFormula(IF( ($A2="") + (B$1="") + ($A2=B$1),, SUM(MMULT(IF((FILTER(Sheet1!$B$2:$L,Sheet1!$A$2:$A<>"")=1) * (Sheet1!$B$1:$L$1=$A2),1,0), SEQUENCE(COLUMNS(Sheet1!$B$1:$L$1),1,1,0)) * MMULT(IF((FILTER(Sheet1!$B$2:$L,Sheet1!$A$2:$A<>"")=1) * (Sheet1!$B$1:$L$1=B$1),1,0), SEQUENCE(COLUMNS(Sheet1!$B$1:$L$1),1,1,0)))))
The first ( ) + ( ) + ( ) tests three OR conditions. If any is true, the cell will be left blank. This is what allows the formula to be dragged all the way right and down without throwing errors and, in essence, "waiting" for new data from the first two formulas above that it can process.
The rest of the formula is too complex to warrant full explanation (e.g., how MMULT works in detail), this being a volunteer-run site. (Writing the formula took more time than I generally spend in a day on this or other forums.) But here's the gist.
Two grids — each formed by an MMULT (matrix multiplication) — are SUMmed. The first MMULT will produce a grid the same size as the Sheet1 grid, filled with 1 only if two conditions are met: that there was already a 1 in that slot and that the name above matches the name to the right in the "Erik Help" grid. Otherwise, the result for that slot is a zero. The second MMULT forms the same size grid based on the same conditions, only this time it gets a 1 only if there is already a 1 and the name above matches the name above the cell in "Erik Help." These two grids are multiplied, and if the product is a 1, we know that BOTH names had a 1 there. Once SUMmed, we get the count of shared projects for those two names.
As this formula is dragged, cell references not locked with a dollar sign will adjust, so that two different names will be compared by the two MMULT grids.
Because this solution requires comparing arrays with arrays with arrays, I don't currently see how a further array solution is possible, hence the need for the formulas to be dragged. That is, each of these formulas is already jam-packed with array processing.
Again, the formula is currently dragged all the way to Column Z and down to Row 200. However, it only references up to Column L (which is as far as your current names list goes). If your real world application has more names and thus carries over past Column L, the easiest way to change all of the formulas at once is this:
Go to the "Erik Help" sheet (which you can, of course, rename as you like).
Hit Ctrl-H to open the Find/Replace dialog box.
Enter $L in the FIND field and $? in the REPLACE field (where ? will be the new column to which you want the results to extend, e.g., $M or $P, etc.)
Choose "This sheet" from the "Search" drop-down.
Check the box next to "Also search within formulas."
Click the "Replace all" button.
If the data set shrinks or grows again, do the same steps, just changing the old furthest column reference for the new furthest column reference.
Here is a super-simple way of doing it which just changes the pair of columns selected in the countifs as the formula moves across and down by relative addressing:
=countifs(index($B$2:$D,0,row(A1)),1,index($B$2:$D,0,column(A1)),1)
pulled down and across.
Attempt at more general solution.
The question is tagged pivot-table. Although a pivot table approach seems useful, the data is in exactly the wrong format to achieve it. The task would be to transform the data from ones and zeroes to column numbers so
1 1 0 => 1 2
1 0 1 => 1 3
1 1 1 => 1 2, 1 3 and 2 3.
This can be achieved by generating pairs of numbers as follows and performing a lookup in the original data:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
The formulas to generate these sequences are
=ArrayFormula(quotient(mod(sequence(90,1,0),9),3)+1)
and
=ArrayFormula(mod(sequence(90,1,0),3)+1)
(9 because there are 3X3 pairs per row of data, 90 because there are 10 rows of data).
The following generates a lookup for each row of data
=ArrayFormula(quotient(sequence(90,1,0),9)+1)
Putting all this together and wrapping it in a pivot query gives
=ArrayFormula(query({vlookup(quotient(sequence(90,1,0),9)+2,{row(B2:D),B2:D},quotient(mod(sequence(90,1,0),9),3)+2,0)*(quotient(mod(sequence(90,1,0),9),3)+1),
vlookup(quotient(sequence(90,1,0),9)+2,{row(B2:D),B2:D},mod(sequence(90,1,0),3)+2,0)*(mod(sequence(90,1,0),3)+1)},
"select count(Col1) where Col1<>0 and Col2<>0 group by Col1 pivot Col2"))
The formula can be generalised to different numbers of rows and columns.
I have a ascending sorted list of irregular dates in Column A:A:
A B C D (A:A,A2:A) E (A:A,A3:A)
2017-11-09 10 10 NA NA
2017-11-10 11 21 1 NA
2017-11-14 15 36 4 5
2017-11-15 22 58 1 5
Column C:C is a rolling sum of B:B. I'm trying to get arrayformula in D:D/E:E to find the datedif between current row (starting date) and X rows above (end date):
=ArrayFormula(DATEDIF(B:B-(X Rows),B:B,"D"))
The goal is to find range of change in D:D over X amount of days:
D:D - D:D-rowX / datedif (A:A-rowX, A:A)
i.e for 2 days on row C4:
(C4-C2) / datedif(C4-2,C4,"D")
(58-21) / datedif(C2,C4,"D")
37 / 5 = 7.4
for 5 days on row C10:
(C10-C5) / datedif(C10-5,C10,"D")
for 15 days on row C20:
(C20-C5) / datedif(C20-15,C20,"D")
I'm trying to calculate X for 1,2,3,4,7,28 rows up which means the array has to start that 1,2,3,4,7,28 rows down.
Right now, the array bugs out to bad reference because the first starting date is DATEDIF(B-X,B1,"D") where B-X is a invalid negative reference. Arrayformulas with bad values instead of bad references seems to just skip past errors and starts working once input are valid. But I can't figure out how to skip bad references. I've tried forcing start date with INDIRECT but can't get it to recognize value as a date. I also tried DATEDIF(B:B, B:B+X,"D"), which spits out the correct numbers but results are offset by X rows. I've tried reverse sorting A:A, =ArrayFormula(if(len(A:A),DATEDIF(SORT(A2:A,1,0),SORT(A:A,1,0),"D"),"")) it produces a reverse orders list of correct answers that I can't figure out how to flip back.
Seems like I'm missing something obvious?
EDIT: tried to clarify original post
Is there a easy way to displace an entire column?
Alternative Solution?
The formula roughly works but is not aligned to the correct row:
C D E
1 2 3
1 2 3
1 2 3
1 2
1
I just need it to display
C D E
1
1 2
1 2 3
1 2 3
1 2 3
To get things aligned, I can put in cell on row2 of Column F:
=array_constrain(ARRAYFORMULA(D:D),COUNT(A:A)-2,1)
Or cell in row3 of Column G:
=array_constrain(ARRAYFORMULA(E:E),COUNT(A:A)-3,1)
But if I try trigger teh formula from row1 via:
=arrayformula(if(row(A:A)>=2,array_constrain(D:D,COUNT(A:A)-2,1)))
It label everythign >=2 row false and still render D:D without displacing the cells the proper number of rows:
C D
1 false
1 2
1 2
1 2
1
EDIT: I'm closing the request, ended up just using vlookup(B:B-X) which provided an approximate enough result to work for my needs.
Short answer
Add the following formula to D1
=ArrayFormula({"N/A";ARRAY_CONSTRAIN(DATEDIF(A:A,A2:A,"D"),COUNT(A:A)-1,1)})
And the following formula to E1
=ArrayFormula({"N/A";"N/A";ARRAY_CONSTRAIN(DATEDIF(A:A,A3:A,"D"),COUNT(A:A)-2,1)})
Explanation
The solution use ARRAY_CONSTRAIN to return just the required result values and use a the array notation to add the required N/A values for the rows that as it don't have a pair to calculate the date difference.
REMARK:
Please note that the DATEDIF functions use the column A for the references as this column is the one that holds the date values.
What I have:
Table 1:
Name / 1 / 2
Peter / Agree / Disagree
So Row 1 will be Name followed by the number 1 - 80. Row 2 will be the name followed by either "Agree" or "Disagree" depending on an answer the user gives on a form.
Example:
Table 2:
Title1 / Title2 / Title3 / Title4
1 / 2 / 3 / 4
5 / 6 / 7 / 8
So Row one is a title row and each title has a column of numbers.
Example:
What I want:
I want to be able to count the number of times a person has put the word "Agree" in table 1 but only for the numbers that appear in each title column in table 2.
Example: If a person put the word "Agree" in table 1 under the numbers 1,3 and 5, then the total for Title1 in table 2 would be 2 where Title2 would be 0, Title3 would be 1, and Title4 would be 0.
Example:
You can see that the last row of each column is how many of the numbers in the Column have the word "Agree" in the other table under the same number.
What I have tried:
So far I am trying to get this working with a COUNTIFS formula. The issue here lies with the fact that I am trying to use a range as BOTH the Criteria Range and the Criteria.
SO, to get around this, I followed the advise given in This Question and came up with the following:
=sum(arrayformula(COUNTIF('Form responses 1'!C1:CD1,C2:C21)))
This works but obviously doesn't take in to consideration the second part of the criteria. My obvious next thought was to try the following:
=SUMPRODUCT(COUNTIFS('Form responses 1'!C1:CD1,C2:C21,'Form responses 1'!C2:CD2,"Agree"))
The issue here is that for some reason is always returns 0 as it doesn't seem to be reading the second criteria.
Question:
Is there a way to have a COUNTIFS formula where both the criteria range and the criteria of the 1 check can be ranges and the the second check can be a standard criteria range and a word as the criteria.
You may consider using countif on array of response lookup like this
=COUNTIF(ArrayFormula(HLOOKUP(C2:C21,'Form responses 1'!$C$1:$CD$2,2)),"Agree")
Change ranges as needed to drag formula down.
Sheet