I have a use case where I need to concatenate values from merged cell with other columns based on condition
Name
Frequency
Old Measure
New Measure
What's needed
Name1
Freq1
Mea1
Name1-Freq1-Mea1
Freq2
Nmea1
Name1-Freq2-Nmea1
Freq3
Mea2
Name1-Freq3-Mea2
Name2
Freq4
Mea3
Name2-Freq4-Mea3
Freq5
Nmea2
Name2-Freq5-Nmea2
Name3
Freq6
Mea4
Name3-Freq6-Mea4
Name4
Freq7
Nmea3
Name4-Freq7-Nmea3
Name5
Freq8
Nmea4
Name5-Freq8-Nmea4
Freq9
Nmea5
Name5-Freq9-Nmea5
The formula should check for column Old Measure and New Measure which ever is filled should concatenate with Name and Frequency.
I did try to take the answer from this similar question - Concatenate merged cells with Google Sheets
and added the check for Old Measure and New Measure column as below but not giving correct results.
=IFS(C1<>"", TEXTJOIN("-",false,INDEX(A:A,LARGE((ISBLANK(A:A)=FALSE)*(ROW(A:A)<=ROW())*ROW(A:A),1)),B1,C1) , D1<>"", TEXTJOIN("-",false,INDEX(A:A,LARGE((ISBLANK(A:A)=FALSE)*(ROW(A:A)<=ROW())*ROW(A:A),1)),B1,D1))
Here's a possible solution:
=ArrayFormula(query(byrow(
{lookup(row(A2:A),row(A2:A)/(A2:A<>""),A2:A),B2:D},
lambda(r,textjoin("-",1,r))),
"limit "&-1+max(if(B2:D<>"",row(B2:D)))))
Explanation
This part
lookup(row(A2:A),row(A2:A)/(A2:A<>""),A2:A)
Fills the gaps in A2:A with the last non-empty value above.
Then
byrow(...,lambda(r,textjoin("-",1,r)))
Concatenates row-by-row the values from the previous array and the values in B2:D.
And finally
query(...,"limit "&-1+max(if(B2:D<>"",row(B2:D)))
Constrains the resulting array to the last filled row.
Related
how to pull column from different sheet..
I've a sheet using the below formula to get the column(n rows) from Sheet1 to Sheet2 however I'm getting zeros after nth row. How to avoid zeros here ??
=IF(NOT(ISBLANK(Sheet1!C1)),Sheet1!C:C,"")
I'm doing the same for A,B,C columns to get data from Sheet1 to Sheet2. Any better formula ?
zeros are coming because the original column doesn't have data after nth row. for example if zero occur at 301 for column c means data in the column C has values upto 300 rows.
we can avoid this issue in two ways
stop copying formula after you get zeros
or
Put a unique word in the formula (here stopcopying)
=IF(LEN(IF(NOT(ISBLANK(Sheet1!C12)),Sheet1!C:C,""))=0,"stopcopying",IF(NOT(ISBLANK(Sheet1!C1)),Sheet1!C:C,""))
Find "Stopcopying" keyword and replace without giving any word ( ctrl F and R)
This is the only way I can see and this answered my question:
=FILTER($B:$E,(B:B<>""))
In this sheet, I've the below input data:
As seen, the courses are separated by /
I want to display the same in the format below, where each line shows one course only, with the data of the student repeated:
I know using =split(C3," / ",true,true) can split the courses into 2 columns at the same row, but I need them in the same column, so I tried =TRANSPOSE(split(C3," / ",true,true)) that is working fine for the first line only, but it fail with using ARRAYFORMULA.
Any thought? I'm opened for any potential solution, formula or script or any other.
UPDATE
I tried this trick, creating a new column showing number of courses for each student as =ArrayFormula(LEN(REGEXREPLACE(C11:C13, "[^/]", ""))+1)
Then using Rep to repeat each row based on the number of courses =arrayformula({transpose(split(concatenate(rept(B11:B13 & ",",D11:D13)),",",false,true)),transpose(split(concatenate(REPT(C11:C13 & ",",D11:D13)),",",false,true))}) then ended up with:
But here, I've the courses still joint together, how can i split them!
I've added two sheets to your sample spreadsheet. "Sheet2" is a cleanup of your testing sheet, "Sheet1." The other sheet ("Erik Help") references Sheet2, not Sheet1, and contains the following formula in cell A1:
=ArrayFormula({"Student ID","Student Name","Course";SUBSTITUTE(SPLIT(QUERY(FLATTEN(SPLIT(FILTER(SUBSTITUTE("/ "&Sheet2!C3:C,"/","/ "&Sheet2!A3:A&"zzz~"&Sheet2!B3:B&"~"),Sheet2!A3:A<>""),"/")),"Select * WHERE Col1 Is Not Null"),"~"),"zzz","")})
This one array formula produces all headers and results.
A virtual array is formed between the curly brackets { }. Headers are introduced first followed by a semicolon, which means "bump down one row to continue." The header titles can be changed as you like.
How It Works:
An addition "/ " is concatenated to the front of every non-blank entry in Sheet2!C2:C. Then SUBSTITUTE replaces every one of these forward slashes with Col A data, "zzz~", Col B data and "~". The tildes (~) will be used later by the outer SPLIT. The "zzz" is added to make sure that ID numbers are converted to text so that they hold formatting throughout the processing and don't turn into real numbers; later, the outer SUBSTITUTE will replace those with null (i.e., get rid of the 'zzz').
Once the initial concatenations are complete, they are SPLIT at the forward slash and then FLATTENed into one column. QUERY removes any blank rows in this virtual array so far. The remaining results are again SPLIT at the tilde. Finally, that outer SUBSTITUTE removes the temporary instances of 'zzz'.
I also added a custom CF formula for the alternating color banding on alternate rows.
You can try this one:
Formula:
=ARRAYFORMULA(TRIM(QUERY(SPLIT(FLATTEN(IF(IFERROR(SPLIT(C3:C5, "/"))="",,
A3:A5&"×"&B3:B5&"×"&SPLIT(C3:C5, "/"))), "×"),
"where Col3 is not null")))
Output:
Reference:
How to transpose & split multiple columns and repeat specific cells in a column
I'm trying to run a formula to identify in which row a total sum is reached.
I've been able to do that calculation when I have an entire range of cells to work with, however, I'm doing a filter / join calculation because I need to do this from an individual row with all the data instead of an entire range of cells.
Here is an example google sheet (EDITABLE - feel free) where you can see the range and working formula (both below). Help getting this from the single-cell versions on the top would be very helpful. The error I get with both row() & index() formulas is that the "argument must be a range".
If there's another way to do this besides the single-cell I had that doesn't require referencing the range (e.g. using FILTER) then I'm open to it.
My desired result is to be able to pull the get the second column (date) at the point when the sum is reached (can be via the INDEX & MATCH formula I used or an alternative). This will tell me the earliest date that feeds into the desired sum.
Yes unfortunately you can't do that trick with SUMIFS to get a running total unless the column being totalled is an actual range.
The only approach I know is to multiply successive values by a triangular array like this:
1 0 0 ...
1 1 0 ...
1 1 1 ...
so you get just the sum of the first value, the first 2 values, then 3 values up to n.
This is the formula in F5:
=ArrayFormula(match(E14,mmult(IF(ROW(A1:INDEX(A1:ALL1000,COUNT(split(A5,",")),COUNT(split(A5,","))))>=
COLUMN(A1:INDEX(A1:ALL1000,COUNT(split(A5,",")),COUNT(split(A5,",")))),1,0),TRANSPOSE(SPLIT(A5,",")))))
And the formula in F6 is just
=to_date(INDEX(TRANSPOSE(SPLIT(B5,",")),F5,1))
EDIT
You might have guessed that the above formula was adapted from Excel, where you try to avoid volatile functions like Offset and Indirect.
I have realised since posting this answer that it could be improved in two ways:
(1) By using Offset or Indirect, thus avoiding the need to define a range of arbitrary size like A1:ALL1000
(2) By implying a 2D array by comparing a row and column vector, rather than actually defining a 2D array. This would give you something like this in F5:
=ArrayFormula(match(E14,mmult(IF(ROW(indirect("A1:"&address(COUNT(split(A5,",")),1)))>=
COLUMN(indirect("A1:"&address(1,COUNT(split(A5,","))))),1,0),TRANSPOSE(SPLIT(A5,",")))))
which could be further simplified to:
=ArrayFormula(match(E14,mmult(IF(ROW(indirect("A1:A"&COUNT(split(A5,","))))>=
COLUMN(indirect("A1:"&address(1,COUNT(split(A5,","))))),1,0),TRANSPOSE(SPLIT(A5,",")))))
Updated: While the solution provided =IF(A2>A1,IF(A2>MAX(A$1:A1),ROW()-1,IFERROR(B1+1,1)),1) does work for the original test data, it doesn't work for a more complex data set, see the second screen shot below:
Original question:
I have a need to process a column (A in the example) of numbers that represents a value changing over time, and establish for how many rows the present row's number has been the largest number, and report that as illustrated in Column B.
What I can't figure out is whether there is a way of producing column B using spreadsheet functions or if I need to write some apps script to do the calculations. I've looked at the usual suspects like MAX() and LARGE() but they don't quite do what I want.
What I want is something like MAXSINCE(A99, A:A98) but that doesn't exist.
Updated data set which still doesn't have an answer for the question: for how many rows has this row had the largest value?
Logic Flow:
Check if current value A2 is greater than previous value A1; If not, return 1
If the above is true, Check whether current value is greater than the present MAX. If so, return current ROW's number - starting offset 1 else add 1 to previous value B1
Code Sample:
B2:
=IF(A2>A1,IF(A2>MAX(A$1:A1),ROW()-1,IFERROR(B1+1,1)),1)
Drag fill down
I've got a google spreadsheet with a main sheet tab. column A contains a bunch of company names, some of which repeat, and are included multiple times. In column B i want to have a predefined unique code for each company. For instance if I had a company name Nike in a10, a14, a21 I would have the same code each time in b10, b14, b21.
I was initially looking at if / else blocks and switch statements (not sure if google spreadsheet can even do them) to accomplish this, but they would become massive and unmanageable as single line pieces of code will involve several hundred company names.
Instead I've setup another tab called Codes Data with a predefined list of all of the company names in column A and the code in column B. This list will be added to over time.
What I'm trying to do is have a formula in the main sheet column B that will check the value of the corresponding column A cell, find the unique code for that company in the Codes Data tab and place that code in column B.
I started using VLOOKUP for this and at first it seemed to work, but now I'm getting inconsistent results (i.e. its outputting Addidas | am-1121 and ACMECO RESTAUR | am-1121 where according to the Codes Data sheet it should output Addidas | ad-5426).
I've provided an example spreadsheet here : https://docs.google.com/spreadsheets/d/156Lla5IyLjB-hp7s50jpotC1qcaov9RdFkpUzATe710/edit#gid=458436476
Is VLOOKUP the correct function to be doing this? If so, how can I use it more properly, and if not what would be a better approach?
You must add FALSE to your lookup formula, or it won't work:
=VLOOKUP(A5, 'Codes Data'!$A:$B, 2, FALSE)
Use the Help menu, and choose "Sheets Help", and then type in "vlookup". You'll get the documentation:
is_sorted - [OPTIONAL - TRUE by default] - Indicates whether the column to be searched (the first column of the specified range) is sorted.
If is_sorted is TRUE or omitted, the nearest match (less than or equal to the search key) is returned. If all values in the search column are greater than the search key, #N/A is returned.
If is_sorted is set to TRUE or omitted, and the first column of the range is not in sorted order, an incorrect value might be returned.
If is_sorted is FALSE, only an exact match is returned. If there are multiple matching values, the content of the cell corresponding to the first value found is returned, and #N/A is returned if no such value is found.