So I have this formula that copies rows (with data in col A) into a new range. Column A contains number indicating how many duplicates the row should yield in the result. Also the output rows gets sorted based on the value in column A.
=sort(arrayformula(vlookup(
transpose(split(query(rept(row(D2:D)&" ",A2:A),,9^9)," ")),
arrayformula({row(D2:D),{A2:A,D2:F}}),
{2,3,4,5},
0)),
1,
TRUE)
This is not exectly what I need thou. Instead of having a single value in the cells in column A that indicates how many times the row should be duplicated I need to have a text string like “2,3,5” in every cell in that column, where the individual numbers in the string indicates the position of the row in output (rather than the number of times the row should be copied).
For example, in the output I want the row with the string “2,3,5” to be copied three times. The output should have one of the rows be 2:nd from top, the other 3:rd from top, and the last one the 5:th from top.
If I could have the A2:A part of this range {A2:A,J2:N} instead contain the matching values for split(A2:A) I think it would do what I want.
This is a copy of my google sheet. Hopefully it's possible to understand what it is I'm trying to achieve.
https://docs.google.com/spreadsheets/d/1sp5DRBwFP0-aG-FvjUPKBmyylz0WoPB63ASOOdUGdnI/edit?usp=sharing
Related
What I want is for a single column (C-L respectively) to count exactly how many cells in their respective row match the same year (from P onward) as the labeled column. So L5(red) will count how many cells from P5-Z5 have "2022" and K8(pink) will count how many cells from P8-Z8 have "2021" in them.
I currently have the number manually entered into each cell, but would like to automate it so it will count the years on its own. Every string of formulas I have tried all come up as error. It was easier to get a second page to count the amount of cells that have a specific word. But now I can't get a single page to count how many cells contain the specific year date in it on its own page.
Here are various logic formulas I've tried. Each of them just comes up as error.
=COUNTIFS(!P5:cc5,(2022))
=COUNTIFS(!p5:cc5,"&2022")
=COUNTIFS(!p5:cc5,\<="2022")
=COUNTIFS(!p5:cc5,"\<=01/01/2022")
=COUNTIFS(!p5:cc5,"\>=01/01/2022",!p5:cc5,"\<01/01/2023")
=COUNTIF(!P5:cc,YEAR(2022))
=COUNTIFS(!P5:cc,"\<="&DATE(2022))
=(COUNTIF(!p5:cc,"\>="01/01/2022)-COUNTIF(!$p$5:$cc,"\>="01/01/2022))
This one is the formula I have for reading the second page to count how many times the specific name shows up. O5 is the cell with the name in it. So I was basing my year counting off this and trying to google my way through it.
=(COUNTIF('Queue List'!$B$3:$D$400,O5))
Sheet layout
As far as I understand you have 10 columns (C-L) that will have to find how many dates in P:CC are in year 2013,2014,2015... right? You can do it like with this formula in C5:
=COUNTIF(ARRAYFORMULA(YEAR($P5:$CC5)),2010+COLUMN())
You're "scanning" the year of the whole row with arrayformula, and then seeing if it matches 2022. In this case I changed 2022 with 2012+COLUMN() so you can drag it or copy and paste to the whole column and the number of column added to 2012 will "calculate" the corresponding year of each column
Another option is to create a whole array with one single formula in C5:
=MAKEARRAY(ROWS(P5:P),10,LAMBDA(r,c,IF(COUNTA(INDEX(P5:CC,r))=0,"",COUNTIF(ARRAYFORMULA(YEAR(INDEX(P5:CC,r))),2012+c))))
Obviously you can adapt it to a specific range. Right now it creates a "rectangle" of 10 columns wide (C-L) and to the bottom of the page (counting the rows between P5 to P (the end of the sheet). "r" and "c" are the number of the row and the column of each cell being calculated (C5 is Row 1, Column 1. D7 is Row 2, Column 3, etc). With INDEX you can select the row to count from the whole range (using that "r" that equals the row), and with c I use the same logic that with the other formula in order to add to 2012+1 in C, 2012+2 in D, 2012+3 in E, etc.
And COUNTA checks first if there is any value in that row, if it doesn't it leaves that row empty (so you won't have a bunch of unnecesary "0"
I'm compiling a list based on the first answers recieved between row N and AF.
I'm using these two formulas:
=INDEX(N2:O2,MATCH(FALSE,ISBLANK(N2:O2),0))
and
=INDEX(R2:AF2,MATCH(FALSE,ISBLANK(R2:AF2),0))
Is there a way to combine them whilst not searching in rows P & Q?
These are generated from a Form response so can't just be switched around.
try:
=INDEX({N2:O2, R2:AF2}, MATCH(FALSE, ISBLANK({N2:O2, R2:AF2}), 0))
If Sheet1 is an intake sheet of form results, you should not add any data, formulas or even formatting to that sheet. It virtually always causes issues. A form intake sheet should be left exactly as it is. A new sheet can then be used to bring over the results of the form intake sheet as you want to see them.
However, since you didn't specify any of that, I will supply a formula written to work in the same sheet as your posted example and in-sheet examples.
Clear an entire column and place the following in the top cell of that column:
=ArrayFormula({"Attendee Name"; IF(E2:E="",,IFERROR(REGEXEXTRACT(TRIM(TRANSPOSE(QUERY(TRANSPOSE(FILTER(IF(N2:AK="",,N2:AK&"~"),N1:AK1=N1)),,COLUMNS(N1:AK1)))),"\s*([^~]+)"),"(none listed)"))})
This one formula will produce a header (the text of which you can change within the formula itself as you lie) and all valid results for all rows.
The inner IF will append a tilde (~) to any non-null entries in the range N2:AK.
FILTER will keep only those columns in this range where the header is the same as the header in N1 (i.e., "Attendee Name").
TRANSPOSE(QUERY(TRANSPOSE( ),,COLUMNS( ))) is colloquially called a "Query smash." It will form one cell from all horizontal results per row.
TRIM will cut any preliminary spaces and form a true string.
REGEXEXTRACT will pull the from the first non-space character up to but not including the first tilde (from those appended in the first step)—in other words, the first full valid entry from any column.
IFERROR will return a message if there is an error, with the likely error being that there were no valid entries for "Attendee name" in any column.
The outer IF will leave the cell blank if the no training event exists in E2:E.
{ } forms a virtual array that places the header over all other results.
ArrayFormula( ) signifies that multiple results will be processed at once.
Because this is an array formula that is being "asked" to process every row, you cannot manually type into any cell of this results column. If you do, you will "break the array"; everything except what you just typed will disappear, leaving only an error in the formula cell. If you need to add or change a name, you need to do that in the raw results range (e.g., manually type a name or a new name in Col N), which will then turn up in the formula output range.
Sample data here.
In my sheet, I mark header rows in the A-column. If all rows between any given header row are marked as "Ignore" in the B-column, then I'd like that header column to format to a different color.
How do you build a formala that can check if the string "Ignore" happens on any number of rows between two A-column cells with a given string?
Checking for an unknown number of rows is beyond my skillset in formula-building.
EDIT:
I've added a few new conditions that make this slightly more complicated.
A top header row, which should be ignored.
Some rows in column A have data in non-header rows. So, the dynamic range has to check for the exact string that marks a header row and how many rows it takes before that string repeats in the column.
Some B-column rows are blank. Blank doesn't mean "Ignore", so if all B-column rows beneath a header are blank, the header shouldn't have the special format.
try:
=(NOT(REGEXMATCH(ROW($A1)&"", INDEX(TEXTJOIN("|", 1, "×",
IFERROR(SORT(UNIQUE(FILTER(VLOOKUP(ROW($A1:$A),
IF($A1:$A<>"", {ROW($A1:$A), ROW($A1:$A)}), 2, 1),
$B1:$B<>"Ignore", $B1:$B<>"")), 1, 0)))))))*($A1<>"")
update:
=NOT(REGEXMATCH(ROW($A2)&"", "^"&TEXTJOIN("$|^", 1, "×",
IFERROR(SORT(UNIQUE(FILTER(IFNA(VLOOKUP(IF(($A2:$A<>"")*($A2:$A<>"*"),, ROW($A2:$A)),
IF(($A2:$A<>"")*($A2:$A<>"*"), {ROW($A2:$A), ROW($A2:$A)}), 2, 1)),
$B2:$B<>"ignore", $C2:$C<>"")), 1, 0)))&"$"))*($A2<>"")*($A2<>"*")
step-by-step formula explanation
This is essentially the same as Player() only a little shorter formula.
=if(A1<>"",len(SUBSTITUTE(TEXTJOIN("",,B2
:INDEX(B:B,MATCH(true,isblank(B2:B),0)+row()-1,1)),"Ignore",""))=0,"")
Explanation of Dynamic Range
The hardest part of this is matching the groups of values in column b. To do this, I used a vector approach of with an index function separating the ranges with a :. So like one would do B2:B3, one could do: B2:Index.
To get the lower position, I used a method of matching the first blank (note ="" won't work). This will identify the distance from the cell the function is being called from. We then need to add the row it's being called from, then one cell higher (less) as we don't want the blank cell, but the one above. So combining... INDEX(B:B,MATCH(true,isblank(B2:B),0)+row()-1,1) gets the dynamic lower value.
After that, there's a variety of ways to solve. I used textjoin and substation to confirm a length of zero as a method, but lots of other ways.
Paste this: formula in C1, to get a helper column that can be hidden.
=AND( A1<>"", LOWER(B2)= "ignore")
Paste this: formula in conditional formatting and set Apply to range to A1:A1000, take a look at Example Sheet
=$B:$B="Ignore"
I am having difficulties trying to get an array formula to increment a column and restart the increment whenever a condition has been met.
Here is an example of what I am trying to achieve, but this has been done manually. It would be great if this could work in an array formula as we'll be adding more rows and would rather not drag the formula down.
[Update based on feedback of the original post]
Column A contains a list of names and teams.
Names are already organised into teams.
The aim is to go through each row and provide a name with an index starting from 1.
Then when a new team is found in column A the index starts again from 0.
The aim is to make this an Array Formula to avoid having to manually re-add the formula when more rows are added.
Link to sheet:
https://docs.google.com/spreadsheets/d/1K00LRFNrN99fFXQO1tzp8jjZeCuTxwENXNGuLj0K0ao/edit?usp=sharing
Example
Any thoughts or advice on this would be greatly appreciated.
I've added a new sheet ("Erik Help") to your sample spreadsheet. It contains the following formula in B1:
=ArrayFormula({"ID Index"; IF(A2:A="",, IF( REGEXMATCH(LOWER(A2:A),"team"), 0, ROW(A2:A) - VLOOKUP(ROW(A2:A), FILTER(ROW(A2:A), REGEXMATCH(LOWER(A2:A),"team")), 1, TRUE)))})
The header text is included in the formula. You can change it as you like.
If a cell in A2:A is blank, the corresponding cell in B2:B will be as well.
If REGEXMATCH finds a match with "team" in the lowercase rendering of a cell in A2:A, 0 will be returned for the corresponding cell in B2:B.
Otherwise, VLOOKUP will lookup each remaining row number in a FILTERed array containing only those row numbers where the word "team" appears. (In your sample set, that will be 2, 8, 12). When the exact match is not found (which it will not be for any remaining row), TRUE tells VLOOKUP that, since the search array is in strict ascending order, we want it to "bump back" to the most recent value found. In each case, the returned row number of the most recent row containg "team" is then subtracted from the actual row number to produce the recurring incremental numbering 1, 2, 3, etc.
try:
=INDEX(IFNA(1*IF(REGEXMATCH(A2:A, "Day"), 0, REGEXEXTRACT(A2:A, "(\d+)"))))
I have a very hard problem to solve, which must be completed with a formula (not a script).
Basically, the Raw input column needs to be dynamically filled down until it hits the next piece of text.
Here's an example file with includes the expected output.
https://docs.google.com/spreadsheets/d/1ibqCvY39NlhCRWsbBdxKITUUpVpp9wXdEz44T-pHDY0/
Is it even possible to achieve?
Thanks
This will work based on your ask, assuming that A2 is never blank, place this in the first row of data (not header):
=ArrayFormula(IF(A2:A<>"", A2:A, B1:B))
It checks to see if there is a value in column A, if there is, it fills that column, if not, it copies the cell above.
Delete everything in Column B (including the header) and place the following formula in B1:
=ArrayFormula({"Header";VLOOKUP(FILTER(ROW(A2:A),ROW(A2:A)<=MAX(FILTER(ROW(A2:A),A2:A<>""))),FILTER({ROW(A2:A),A2:A},A2:A<>""),2,TRUE)})
Here is a basic explanation of how this formula works:
A virtual array is created between the curly brackets { }; this virtual array contains a header and all results. You can change the header name to whatever you like.
VLOOKUP looks up every row number that is less than or equal to the highest row number that contains text in A2:A. Each of these qualifying rows is looked up in a second array that contains only the row numbers and Column-A data from non-blank rows, returning the data itself. Since rows are in perfect ascending order and the last parameter of VLOOKUP is set to TRUE, all blank rows in the first array will "fall backward" to find the most recent row that did have something in Column A.