This question already has answers here:
Apply formula to the entire column
(16 answers)
Closed 5 months ago.
Having a problem with VLOOKUP under Google Sheets.
I have this basic command that I am trying to assign to each row of a column (there are 200 rows):
=Vlookup(D1,KDCAssets!A1:F500,5,false)
I want to assign this to a column. When doing so, I am expecting something like this:
Row 1 =Vlookup(D1,KDCAssets!A1:F500,5,false)
Row 2 =Vlookup(D2,KDCAssets!A1:F500,5,false)
Row 3 =Vlookup(D3,KDCAssets!A1:F500,5,false)
Row 4 =Vlookup(D4,KDCAssets!A1:F500,5,false)
The D value increases but A and F values remain the same ( i.e. A1 and F500 ). But what I am getting is something like:
Row 1 =Vlookup(D1,KDCAssets!A1:F500,5,false)
Row 2 =Vlookup(D2,KDCAssets!A2:F501,5,false) <- increases by 1
Row 3 =Vlookup(D3,KDCAssets!A3:F502,5,false) <- increases by 1
Row 4 =Vlookup(D4,KDCAssets!A4:F503,5,false) <- increases by 1
The range values starting with A1 and F500 increases with each successive row. But, for the lookup, I need to be the same for each row. How can I get this to act properly?
TIA
You can use new lambda function BYROW() to make it dynamic spill array.
=BYROW(D1:INDEX(D1:D,COUNTA(D1:D)),LAMBDA(x,Vlookup(x,KDCAssets!A1:F,5,false)))
Here D1:INDEX(D1:D,COUNTA(D1:D)) will return a array of values as well cell reference from D1 to last non empty cell in column D (Assume you do not have any blank rows inside data). If you have then you have to use different approach. See this post by #TheMaster
Then LAMBDA() will apply Vlookup() function for each cell of D column.
Related
I have a table with three Columns:
Column A: name of Item,
Column B: Lowest value of series,
Column C: the Highest value of series.
enter image description here
What I want to achieve is:
Generate series of item sequence from lowest number to highest number per row
So Apple 7 9 will yield: "Apple_7", "Apple_8", "Apple_9"
Concatenate/Join such sequence per row into Column D
So
Item
From
Until
Result
Apple
7
9
"Apple_7, Apple_8, Apple_9"
Berry
3
8
"Berry_3, Berry_4, Berry_5, Berry_6, Berry_7, Berry_8"
Doing it all using one Arrayformula, so that new row added can be automatically calculated.
Here is example sheet: https://docs.google.com/spreadsheets/d/1R5raKmmt5-aOIorAZGHjv_-fdySKWjCMB_FRQwm1vag/edit#gid=0
I tried in Column D:
arrayformula(textjoin(", ",true,arrayformula(A3:A&"_"&sequence(1,C3:C-B3:B+1,B3:B,1))))
Apparently, the sequence function only take value from Column B and join it in first row.
Any help will be appreciated.
Try below BYROW() formula (see your file, harun24hr sheet).
=BYROW(A3:INDEX(A3:A,COUNTA(A3:A)),LAMBDA(x,TEXTJOIN(";",1,INDEX(x&"_"& SEQUENCE(INDEX(C:C,ROW(x))-INDEX(B:B,ROW(x))+1,1,INDEX(B:B,ROW(x)))))))
Here A3:INDEX(A3:A,COUNTA(A3:A)) will return a array of values as well cell reference from A3 to last non empty cell in column A (Assume you do not have any blank rows inside data). If you have blank row, then you have to use different approach. See this post by #TheMaster
Then LAMBDA() will apply TEXTJOIN() and SEQUENCE() function for each cell of B as well as C column.
SEQUENCE() will make series from start to end number and by concatenating A column and will generate your desired strings.
Finally TEXTJOIN() will join all those strings with delimiter to a single cell.
try REDUCE:
=INDEX(QUERY(REDUCE(, A3:INDEX(A:A, MAX(ROW(A:A)*(A:A<>""))),
LAMBDA(x, a, {x; JOIN(, LAMBDA(i, f, u, i&"_"&SEQUENCE(1, u-f+1, f)&";")
(a, OFFSET(a,,1), OFFSET(a,,2)))})), "offset 1", ))
In my Google Sheet, I have 1000+ rows of Date entries. For each Date, I am calculating the Month# and Week# using MONTH() and WEEKDAY() functions respectively.
Here is the link to a sample file: https://docs.google.com/spreadsheets/d/1Af5-pYMFWZ1QtLoaAbPZYMGRvk43JBslUp4KyOFADfA/edit?usp=sharing
Problem Statement:
For all rows which have a unique Month# and Week#, I would like to implement a formula and calculate Output. For example, in my sheet, rows 3 to 6 pertain to Month=1 and Week=4. For this set of 5 rows I am calculating Output column as the subtraction from the first element in that set (ie... C3-$C$3, C4-$C$3, C5-$C$3 so on ). Similarly row 7 to 10 pertain to Month=1 and Week=5, and so I calculate Output
as Data-$C$7 and so on.
How do I implement this structure to calculate Output column on each set of unique Month# and Week# values?
Delete everything from Column F (including the F2 header). Then place the following formula into cell F2:
=ArrayFormula({"Output";IF(C3:C="",,IFERROR(C3:C-VLOOKUP(E3:E,{E3:E,C3:C},2,FALSE)))})
This one formula will create the header and return results for all valid rows.
Since VLOOKUP always finds only the first matching instance of what it is looking up, we can use it to ask that each value in C3:C subtract that first instance of where week-number match for each row.
By the way, although you didn't ask about this, you can also use this type of array formula in Columns D and E, instead of all of the individual formulas you have. To do that, delete everything from Columns D and E (including the headers). Then...
Place the following formula in D2:
=ArrayFormula({"Month #";IF(B3:B="",,MONTH(B3:B))})
... and the following formula in E2:
=ArrayFormula({"Week #";IF(B3:B="",,WEEKNUM(B3:B))})
My intention is to convert a single line of data into rows consist of a specific number of columns in Google Sheets.
For example, starting with the raw data:
A
B
C
D
E
F
1
id1
attr1-1
attr2-1
id2
attr2-1
attr2-2
And the expected result is:
(by dividing columns by three)
A
B
C
1
id1
attr1-1
attr1-2
2
id2
attr2-1
attr2-2
I already know that it's possible a bit manually, like:
=ARRAYFORMULA({A1:C1;D1:F1})
But I have to start over with it every time the target range is moved OR the subset size needs to be changed (in the case above it was three)!
So I guess there will be a much more graceful way (i.e. formula does not require manual update) to do the same thing and suspect ARRAYFORMULA() is the key.
Any help will be appreciated!
I added a new sheet ("Erik Help") where I reduced your manually entered parameters from two to one (leaving only # of columns to be entered in A2).
The formula that reshapes the grid:
=ArrayFormula(IFERROR(VLOOKUP(SEQUENCE(ROUNDUP(COUNTA(7:7)/A2),A2),{SEQUENCE(COUNTA(7:7),1),FLATTEN(FILTER(7:7,7:7<>""))},2,FALSE)))
SEQUENCE is used to shape the grid according to whatever is entered in A2. Rows would be the count of items in Row 7 divided by the number in A2 (rounded to the nearest whole number); and the columns would just be whatever number is entered in A2.
Example: If there are 11 items in Row 7 and you want 4 columns, ROUNDUP(11/4)=3 rows to the SEQUENCE and your requested 4 columns.
Then, each of those numbers in the grid is VLOOKUP'ed in a virtual array consisting of a vertical SEQUENCE of ordered numbers matching the number of data pieces in Row 7 (in Column 1) and a FLATTENed (vertical) version of the Row-7 data pieces themselves (in Column 2). Matches are filled into the original SEQUENCE grid, while non-matches are left blank by IFERROR
Though it's a bit messy, managed to get it done thanks to SEQUENCE() function anyway.
It constructs a grid by accepting number of rows/columns input, and that was exactly I was looking for.
For reference set up a sheet with the sample data here:
https://docs.google.com/spreadsheets/d/1p972tYlsPvC6nM39qLNjYRZZWGZYsUnGaA7kXyfJ8F4/edit#gid=0
Use a custom formula
Although you already solved this. If you are doing this kind of thing a lot, it could be beneficial to look into Apps Script and custom formulas.
In this case you could use something like:
function transposeSingleRow(range, size) {
// initialize new range
let newRange = []
// initialize counter to keep track
let count = 0;
// start while loop to go through row (range[0])
while (count < range[0].length){
// add a slice of the original range to the new range
newRange.push(
range[0].slice(count, count + size)
);
// increment counter
count += size;
}
return newRange;
}
Which works like this:
The nice thing about the formula here is that you select the range, and then you put in a number to represent its throw, or how many elements make up a complete row. So if instead of 3 attributes you had 4, instead of calling:
=transposeSingleRow(A7:L7, 3)
you could do:
=transposeSingleRow(A7:L7, 4)
Additionally, if you want this conversion to be permanent and not dependent on formula recalculation. Making it in run fully in Apps Script without using formulas would be neccesary.
Reference
Apps Script
Custom Functions
I'd like to insert 2 column wide fields under each other. I tried with embedded arrays but was not successful.
So basically from:
a 1 e 5
b 2 f 6
c 3
I would like to get:
a 1
b 2
c 3
e 5
f 6
I tried with
={{A:A,B:B};{C:C,D:D}}
but could not get it working, however
={{A:A,B:B},{C:C,D:D}}
put the columns the same as they were so its intresting that with ; its not working.
The blocks are always 2 column wide but the rows are different length
Thanks for your help in advance!
Try:
=filter({A:B;C:D},{A:A;C:C}<>"")
This will return rows where Columns A or C are not blank.
Just under c assuming a is in A1:
=ArrayFormula(C1:D2)
You're not going to find a clean built-in formulaic solution to this one that doesn't utilize some sort of built-in magic auto expansion (like pnuts's answer). Here is my approach using OFFSET that will also work in Microsoft Excel.
In two columns, copy this formula.
=OFFSET($A$1,(ROW()-ROW($G$1))/2,IF(MOD(ROW()-ROW($G$1),2)=1,2,0))
In the second column, modify the formula, adding 1 to the column offset parameter:
=OFFSET($A$1,(ROW()-ROW($G$1))/2,1+IF(MOD(ROW()-ROW($G$1),2)=1,2,0))
where $A$1 is replaced with the address of the top left of your range and $G$1 is the starting location of your output range. This should be resistant to auto-update of formulas from range insertions and deletions (which I despise butchering my formulae and conditional formatting rules) by using only the bare number of references, which are all absolute.
This works by dividing the row offset from your starting position by 2 and rounding down (via an implicit cast to integer when used as a parameter to the OFFSET function) to get the row number of your input range. Then it shifts over 2 columns on every odd row to get data from the second column pair.
Note this is not a size-aware function, so it interweaves the second column pair:
a 1
e 5
b 2
f 6
c 3
I am trying to generate a random Cell from specific range:
I need to each cell Row to generate a random selection from a a specific column (range)
below is a picture of my set up and my failed attempts:
You can do this like this:
Add a random number next to your data set using =RAND(). I've used column B, but you can put it wherever you like.
Add this formula to cells C2 to H2
=INDEX($A$2:$A$21,RANK.EQ(INDEX($B$2:$B$21,COLUMN()-2),$B$2:$B$21))
How it works:
RAND() returns a random number in the range [0..1) This is used as a random sort order for your data
Breaking down the formula:
COLUMN()-2 returns a sequential number 1..6 for columns C to H
INDEX($B$2:$B$21, ... ) returns the 1st to 6th number from the random number list
RANK.EQ( ... ,$B$2:$B$21) returns the position of the random number in the sorted random number list, 1..20.
=INDEX($A$2:$A$21, ... ) returns an item from your data set, based on the random rank from above.
Note: This will return a new randon sample each time Excel recalculates.
The only way to make a random selection that does not repeat is to make an array of integers, than randomize it, and than take out one by one.
For example you start with:
1 2 3 4 5 6 7
you randomize it (swap elements randomly)
2 4 5 1 7 3 6
than you take elements out one by one. (keep an index of how much elements you used in some cell)
Ok here is one trick, add another column with random numbers, than select both random column and range column and click the sort button (picture is from libreoffice but there is a similar button in excel) This will randomize your range column. Than you simply assign values to "w-1" : "w-6" like this =B2, =B3, =B4, =B5, =B6, =B7
I tried this and it works like you wanted, the only problem is it will shuffle values in your range column.