I am wondering if there is a way to do what I want more automatically, i've been doing it with good old regular copy paste but it's taking a lot of time, I need to take the horizontal data I have currently and put it vertically while keeping the first column for each rows, the first column is my "main" part number and I need to link all the other numbers starting from column B to this main part number, example below,
I sometimes have hundreds of rows and columns to do this for, here is what i'm working with
[1]: https://i.stack.imgur.com/dIyZv.png
And here's what the end result needs to look like;
[2]: https://i.stack.imgur.com/PvxGh.png
Thank you in advance!
It can be achieved either with VBA Code or with formulas. I did it with formulas and will try to show you how below.
I have one sheet with all the data, lets call it Sheet1. It looks like this:
Then, I have another sheet which returns what you want (Sheet2). It looks as follows:
Note that the first two columns are necesary for the formulas to work. The actual result is on Columns C and D.
Now, below are the formulas (or values) you would need to put in Sheet2 to make it work:
Cell A1: 0
Cell B1: 1
Cell A2: IF(B2=1,A1+1,A1)
Cell B2: IF(B1+1=$G$1,1,B1+1)
Cell C1: OFFSET(Sheet1!$A$1,A1,0)
Cell D1: OFFSET(Sheet1!$A$1,A1,B1)
Cell G1: The number of columns in the data on Sheet1
Then, just drag the formulas (not the values in A1, B1), until you have the expected result.
I would suggest you try to implement this simple example first, and then move it to your actual spreadsheet.
Let me know how it goes.
EDIT: Regarding your comment, we could do a trick to make it work for a variable number of columns.
First, lets add some variability to the number of columns in Sheet1. This is how my new Sheet1 looks like:
On Sheet2 I added a formula to count the number of columns per row. See Column F below:
Then, the trick is to change the formulas in Column B in Sheet2:
Before: Cell B2: IF(B1+1=$G$1,1,B1+1)
After: Cell B2: IF(B1+1=OFFSET($F$4,A1,0),1,B1+1)
Note: My formula to count the number of columns per row is:
Cell F4: COUNTA(Sheet1!A1:D1)
Note: Change D1 to the max column in Sheet1. Eg. M1.
Note2: You can get rid of cell G1 now.
Start with column B and everything else becomes a doddle. I only use 1 formula for column B and no more than 1 or 2 for column A (there are 3-4+ methods, no need to duplicate yourself but choose any of them to construct A).
I'm only using 1 formula to make each column. Entire job task done in a minute-5.
Column B. Do this first for all your "column B's":'
=IF(ROW(A1)=1,INDEX(A$1:T$1,INT(((ROW()-20)/20+1-ROW($A$1))/COLUMNS(A$1:T$1))+1,MOD(ROW()-20-ROW($A$1),COLUMNS(A$1:T$1))+1),INDEX(A$1:T$1,INT(((ROW()-20)/20+1-ROW($A$1))/COLUMNS(A$1:T$1))+1,MOD(ROW()-20-ROW($A$1),COLUMNS(A$1:T$1))+1))
So all you have to do is drag down. Change only the row references to refer to your 100's if different rows you need to do this for. 1 minute. Job done
for 30 columns/cells change T to AD, for 200 cells , change T to GR, etc. You can also force it to stop at number of your choice.
If you put it anywhere else, it will still work, but your going to have to jiggy with the math a bit to get it to start from the the first entry in the row ( or the specific Wherever you want). Its up to you.
It acts like a modular clock. Been using it for a few years. Ticker tape. Rolling slabs of concrete laying out for you.
here, this is what I get when I plug it into the first row of any column , referring to a 20 field length header on my sheet.
Etc... It continues forever (or for however long you want it). (and you can change the mod anytime).
The first argument you could change to whatever your requirements are , for instance , if(LEN(F8)<1, or whatever, to Start/"Set the clock."
And For any corresponding ranges (your first column for each) (** Your "Column A's" **):
=IF(LEN(H20)<1,K21,H20)
or you can use this logic. It Becomes elementary.
=IF(J21=K21,J21,J20)
Better if you use this starting from row 2 on each column A: if(and(j1=it's next door neighbour, row(it's next door neighbour cell=1)), it's self j1,.. blah blah blah blah
OR AM I MISSING THE POINT ?
Method for getting column A;
Since you already have B, A becomes a simple trivial matter. Like cell =$fixed$cell , i.e. A1=$B$1 and drag down.
simple. headache over. game over. Its all effortless.
But if you want me to elaborate more ,
method 2 for getting 1st column, column A's;
=IF(LEN(AV1)>1,IF(ROW(AV1)=1,AV1,INDIRECT("Av"&1)),"")
=IF(ROW(B1)=1,B1,INDIRECT("B"&1)) <---- drag down from row 1
Method 1 for getting 1st column;
=IF(LEN(AV1)>1,$AV$1,"") <----- drag down from row 1
Method 3, below was my favourite:
=$B$1 <---- from row1 drag down (where row1 was just = column B, cell b1, a1=b1) easy peasy .
You could always demand a further simplification of M3:
A1=if(len(b1)>1,$b$1,"") <--drag down from b2 (where b1 was already set) *probably best because only returns a value as long as column B is .otherwise returns blank.
It's like handling duplicates by formula. Similar .
there was a method 4 too. bUt its late. (Written # 02:00)
Or did I miss the point? It's easy. Imo
Im only using 2 formulas. 1 for each column you need done . do column B first, and colimn A becomes a matter of fact . A doddle.
method 1 is my new favourite.
Its late, my naighbours have pissed me off again. Pardon my fonts and writing but seriously. didnt expect this. some people need to go to jail.(my naighbours)
So in the end: 1 formula for B. 1 for A (any one of any the 4+ methods. There are more also) , plug in and scroll for all the rows you need this done for . takes you 30 seconds? 5 minutes tops for all your rows.
Related
I'm learning to use array formulas and have been successful doing simple things like adding 2 columns together in a third column. For example, I can put =arrayformula(B:B+C:C) in D1 and it adds B and C for each row.
But now I have a situation where I want to subtract two numbers in the same column. I want to take the value of that column in the current row and subtract the previous row's value from it. Without array formulas this is simple: in O7 I put =N7-N6 and cop that down so O8 gets =N8-N7, etc. But that requires copying down every time - can I do the same thing with an array formula?
Basically, can I do something like =arrayformula(B:B+(B-1):(B-1)) ?
Context: column N is a monthly account balance. I would like to calculate how much that balanced changed each month. So for row 7, =N7-N6 gives me that difference. But I'm changing the entire spreadsheet to array formulas so I can stop pasting all of the formulas and I'm stuck on this one since it's comparing the same column.
I'm trying to get everything into Row 1 so my values and calculations can start in Row 2. For example, here's one of my formulas in Row 1:
arrayformula(if(row(A:A)=1,"Total gross income",if(LEN(B:B),B:B+C:C,"")))
Unfortunately, in Column O (the one I asked about originally) if I do this:
=arrayformula(if(row(A:A)=1,"Amount saved this month",if(row(A:A)>1,if(LEN(N:N),N2:N-N:N,""))))
Or this:
=arrayformula(if(row(A:A)=1,"Amount saved this month",if(row(A:A)>1,if(LEN(N:N),offset(N:N,1,0)-N:N,""))))
Every row is off by 1 - the result that should go in Row 3 goes in Row 2, etc. And if I do this:
=arrayformula(if(row(A:A)=1,"Amount saved this month",if(row(A:A)>1,if(LEN(N:N),N:N-offset(N:N,-1,0),""))))
Then it gives me an error because the offset function is trying to evaluate something out of range (possibly it starts with N1 and tries to grab a value 1 row above N1?)
Any advice on how to handle that out-of-range error?
I think the error is because of offset range N:N which starts from N1 and you are trying to shift it -1 or one cell up, which brings the formula out of sheet.
Try this formula instead:
=arrayformula(
{"Amount saved this month";
if(LEN(N2:N),N2:N-offset(N2:N,-1,0),"")})
It uses {} to make an array. See more info:
https://support.google.com/docs/answer/6208276?hl=en
Bonus. There is no reason to check row number now.
I have the following formula to return the value of the last value in a column:
=LOOKUP(2,1/(D:D<>""),D:D)
What I need now is to return the value of the cell adjacent to it as well. (It will not necessarily be the last value in that column and the info in Column D could have duplicates.
If your data looks like this:
A 1
A 2
A 3
B 4
B 5
B 6
C 7
To get last value this will do the trick:
=INDIRECT("B"&COUNTA(A:A))
And to get last where value is A:
=INDIRECT("B"&MATCH("A",A1:A7,0)+COUNTIF(A1:A7,"A")-1)
Just use next column:
=LOOKUP(2,1/(D:D<>""),E:E)
Ok, So I have found an answer by playing around with array formulas.
The problem was that this is a stock control sheet where there are changes made at multiple times, each recorded in the next available row. There is always a date (Column E) but not necessarily a Supplier, as it might be stock moving out. When a Supplier delivers, the Supplier name is recorded in Column D. In D1 the last supplier is then shown with the following formula.
=LOOKUP(2,1/(D:D<>""),D:D)
I want to then see what date it was last received. The formula I found that works is as follows (Array Formula):
=INDEX(E:E,MAX(IF(D:D=D1,ROW(D:D)-ROW(INDEX(D:D,1,1))+1)))
This is generally how I do it:
=XMATCH(FALSE,ISBLANK(A:A),0,-1)
This is what each part does:
Parameter
Explanation
FALSE
Instructs Excel to find the first instance of FALSE that it finds
ISBLANK(A:A)
Takes in the column A:A and notionally assigns a value to every item in the column
0
Means we want an exact match. Probably not necessary to put in, but I think it's good practice anyway
-1
Instructs Excel to start the search at the bottom/right of the range and work up/left. If you change this to 1 (the default), Excel will begin the search at the top/left and work down/right
So, taken together, this will search from the bottom of the column A:A, until Excel finds the first cell that is not blank, and return that cell.
Also, yes, this equation can be changed to a row format (e.g. 1:1), and can take a smaller range (e.g. A1:A20), but it cannot take a 2-dimensional range (e.g. A1:B20).
As a practical matter, this approach is much faster than other approaches (and much faster than you'd think, given it's evaluating against every row/column in the range), and won't get fooled by columns that have empty spaces in them (like with a COUNTA style approach).
Hi all,
I have this excel where by I need to find the location of the item if they are found in column B.
So In my F column, I tried to write ifelse formula which didnt work.which is
=IF(D2="NULL","NONE",C((D2))).
My idea is if D2 is not null, use the value in D column to find the location in C column. In this example, fish no 4, so it is found, my F column should show the value "C" using the value shown in D column and use it as Row no in C column
I hope you guys get the idea and help me out a newbie in excel. Thanks in advance
=vlookup($D2,$A$2:$C$6,3,0)
you can use that in column F. Place that formula in F2 and copy down.
you could technically use it in column E as well, but you would need to change the 3 to a 2.
you did not say what you wanted to do if the D value was "Null" so I am going to take a stab at the dark and wrap you lookup formula in an if statement that will deal with "Null" or empty cells
=IF(OR($D2="NULL",$D2=""),"",VLOOKUP($D2,$A$2:$C$6,3,0))
That is the alternative formula to place in F2 and copy down.
Use the formula:
=IF(D2<>"NULL",VLOOKUP(D2,A2:C6,3,FALSE),"Value is NULL")
Here is the working example:
Put formula in cell F2 and drag it down.
[edit]to pull proper location column, not just the row #[/edit]
Seems like a job for MATCH+OFFSET
Try this formula in cell F2:
=OFFSET($C$1, MATCH(E2,B:B,0)-1, 0, 1, 1)
Match is used to locate the value in the first argument (ie E2) within the range specified in 2nd argument (ie B:B). I use B:B but you could also use range B2:B30 or whatever more specific range you want. (I prefer the more generic B:B, though :) )
Third paramter "0" just indicates "Exact match".
This function will retun "#N/A" if nothing found.
OFFSET takes the result from MATCH to pick out the Location you want. The first parameter in OFFSET is the rows below (or above if negative) from the base row (in this case $C$1). the next is the column: 0 since we're in the column we want to be in. The last two are the size of the range: 1,1 is a 1x1 cell, so just 1 cell. If we did ...,2,3), that would be 2 rows high and 3 columns wide - or a 6 cell range. We're just after 1 cell here.
I've always preferred MATCH + OFFSET to other options, I just found they held up more robustly to changes in a sheet (ie new rows/columns added). So it's mostly personaly preference over VLOOKUP and INDEX. I honestly have never compared their actual performance, however, I've never had any issues with MATCH+OFFSET running slowly :)
I am going crazy over this. It seems so simple yet I can't figure this out. I have two worksheets. First worksheet is my data. Second is like an answer key. Upon checking checking, A1:B1 in Sheet 1 is a match with the conditions in Row 52 in SHEET 2, therefore, the value in Column C is "MGC". What is the formula that will perform this function? It's really hard to explain without the data so I pasted a link of the sample spreadsheet. Thank you so much in advance.
sample spreadsheet here. https://docs.google.com/spreadsheets/d/1_AjuNfCdGfEM-XkqPa6W4hSIxQg4NM2Vg4c2C1pQ_vQ/edit?usp=sharing
screenshot here. (wont let me post i have no reputation)
In Sheet2, insert a column in front of Column A and put the formula in A2 =C2&D2.
Then in Sheet1, Cell C2 the formula =vlookup(A2&B2,Sheet2!A:B,2,0).
the first make a concatenated key to lookup, then the second looks up that key.
How about a index(match())? If I've understood correctly you need to match across both the A and B column in sheet one, checking for the relevant values in B and C on sheet 2 to retrun worksheet 2 column a to worksheet 1 column c.
third version try:
=INDEX(Sheet2!$C$1:$C$360,MATCH(Sheet1!A1&Sheet1!B1,Sheet2!$B$1:$B$360&Sheet2!$C$1:$C$360,0))
Basically what this does is use concatenation, the & operator, to specify you are looking for "Criteria A" & "Criteria B" in sheet 1, which makes the string "Criteria A Criteria B", which is supplied in the first part of the match function.
In the second it then says match this against all of my variables in sheet 2 in the same way with concantenation.
The final part of match function (0) specifies you want an 'exact' match
It then supplied this as a reference to the index function, which then finds the row intersecting with the value you want, and returns that.
As noted here https://support.microsoft.com/en-us/kb/59482 this is an array formula, so it behaves differently, and must be input differently. https://support.office.com/en-za/article/Guidelines-and-examples-of-array-formulas-7d94a64e-3ff3-4686-9372-ecfd5caa57c7
There are (at least) 2 ways you could do this without VBA.
USING A SORTED LIST
The first relies on the assumption that your data can be re-sorted, so that everything "Unreported" is in the top, and everything "reported" is together below that (or vice versa). Assuming that this is the case (and it appears to already be sorted like this),we will use the function OFFSET to create a new range which shows only the values that align with either being "Unreported" or "Reported".
Offset takes a given reference to a point on a sheet, and then moves down/up & left/right to see what reference you want to return. Then, it returns a range of cells of a given height, and a given width. Here, we will want to start on Sheet2 at the top left, moving down until we find the term "Unreported" or "Reported". Once that term is found, we will want to move one column to the right (to pull column B from sheet 2), and then have a 'height' of as many rows as there are "unreported" or "reported" cells. This will look as follows in A1 on sheet 1, copied down:
=OFFSET(Sheet2!$A$1,MATCH(A1,Sheet2!A:A,0)-1,1,COUNTIF(Sheet2!A:A,A1),1)
This says: First, start at cell A1 on sheet2. Then find the term in A1 (either "unreported" or "reported", on sheet2!A:A (we subtract 1 because OFFSET starts at A1 - so if your data starts at A1 we need to actually stay at "0". If you have headers on sheet2, you will not need this -1). Then, move 1 column to the right. Go down the rows for as many times as Sheet2 column A has the term found in Sheet1 A1. Stay 1 column wide. Together, this will leave you with a single range on sheet2, showing column B for the entire length that column A matches your term in sheet1 A1.
Now we need to take that OFFSET, and use it to find out when the term in Sheet1 B1 is matched in Sheet2 column B. This will work as follows:
=MATCH(B1,[FORMULA ABOVE],0)
This shows the number of rows down, starting at the special OFFSET array created above, that the term from B1 is matched in column B from sheet2. To use this information to pull the result from column C on sheet 2, we can use the INDEX function, like so:
=INDEX([FORMULA ABOVE],MATCH(B1,[FORMULA ABOVE],0))
Because this would be fairly convoluted to have in a single cell, we can simplify this by using VLOOKUP, which will only require the OFFSET function to be entered a single time. This will work as follows:
=VLOOKUP(B1,[FORMULA ABOVE],2,0)
This takes the OFFSET formula above, finds the matching term in B1, and moves to the 2nd column to get the value from column C in sheet2. Because we are going to use VLOOKUP, the offset formula above will need to be adjusted to provide 2 columns of data instead of 1. Together, this will look as follows:
FINAL FORMULA FOR SHEET1, C1 & COPIED DOWN
=VLOOKUP(B1,OFFSET(Sheet2!$A$1,MATCH(A1,Sheet2!A:A,0)-1,1,COUNTIF(Sheet2!A:A,A1),2),2,0)
OPTION USING ARRAY FORMULAS
The above method will only work if your data is sorted so that the REPORTED and UNREPORTED rows are grouped together. If they cannot be sorted, you can use an ARRAY FORMULA, which essentially takes a formula which would normal apply to a single cell, and runs it over an entire range of cells. It returns an array of results, which must be reduced down to a single value. A basic array formula looks like this [assume for this example that A1 = 1, A2 = 2...A5 = 5]:
=IF(A1:A5>3,A1:A5,"")
Confirm this (and all array functions) by pressing CTRL + SHIFT + ENTER, instead of just ENTER. This looks at each cell from A1:A5, and if the value is bigger than 3, it gives the number from that cell - otherwise, it returns "". In this case, the result would be the array {"";"";"";4;5}. To get the single total of 9, wrap that in a SUM function:
=SUM(IF(A1:A5>3,A1:A5,""))
In your case, we will want to use an array formula to see what row in Sheet2 matches A1 from Sheet1, and B1 from Sheet1. This will look like this:
=IF(Sheet2!$A$1:A$100=A1,IF(Sheet2!$B$1:$B$100,ROW($B$1:$B$100),""),"")
This checks which rows in column A from sheet 2 match A1. For those that do, it then checks which rows in column B from sheet 2 match B1. For those, it pulls the row number from that match. Everything else returns "". Assuming no duplicates, there should only 1 row number which gets returned. To pull that number from the array of results, wrap the whole thing in a MATCH function. Now that you have the row number, you can use an INDEX function to pull the result in Column C with that row, like this:
FINAL ARRAY FORMULA METHOD
=INDEX($C$1:$C$100,MAX(IF(Sheet2!$A$1:A$100=A1,IF(Sheet2!$B$1:$B$100,ROW(Sheet2!$B$1:$B$100),""),"")))
Remember to confirm with CTRL + SHIFT + ENTER instead of just ENTER, when you type this formula. Note that I didn't refer to all of Sheet2!A:A, because array formulas run very slowly over large ranges.
The following formula should work without making any changes to the datasheets.
=INDEX(Sheet2!$A$1:$A$360,MATCH(Sheet1!A1,IF(Sheet2!$C$1:$C$360=Sheet1!B1,Sheet2!$B$1:$B$360),0))
Remember to save this formula as an array with CTRL+SHIFT+ENTER
Documentation on how to use INDEX and MATCH against multiple criteria can be found on Microsoft Support.
It's not clear what you want to do with the multiples that do not have corresponding matches. txed is listed as Unreported twice in Sheet1; kntyctap is listed as Unreported three times. There are only one corresponding match on Sheet2 for each of these.
Non-array Standard Formulas for multiple criteria matches
For Excel 2010 and above use this standard formula in Sheet1!C1:
=IFERROR(INDEX(Sheet2!$A$1:$A$999,AGGREGATE(15,6,ROW(1:999)/((Sheet2!$B$1:$B$999=A2)*(Sheet2!$C$1:$C$999=B1)), COUNTIFS(A$1:A1, A1, B$1:B1, B1))), "")
For version of Excel prior to 2010 use this standard formula in Sheet1!C1:
=IFERROR(INDEX(Sheet2!$A$1:$A$999, SMALL(INDEX(ROW($1:$999)+((Sheet2!$B$1:$B$999<>A1)+(Sheet2!$C$1:$C$999<>B1))*1E+99, , ), COUNTIFS(A$1:A1, A1, B$1:B1, B1))), "")
I've handled error with the IFERROR function in that latter formula. Excel 2003 and previous may have to use an IF(ISERROR(..., ...)) combination.
I have the following formula in my B:B column
=VLOOKUP(A1;'mySheet'!$A:$B;2;FALSE)
It does output in B:B the values found in the mySheet!B:B where A:A = mySheet!A:A. It works fine. Now, I would like to also get the third column. It works if I add the following formula to the whole C:C column:
=VLOOKUP(A1;'mySheet'!$A:$C;3;FALSE)
However, I'm working with more than 100k lines and about 40 columns. I don't want to do 100k * 40 * VLOOKUP, I would like to only do it 100k and not have to multiply this by all the columns. Is there a way (with array-formulas maybe) to just do the VLOOKUP once per line to get all the columns I need?
data example
ID|Name
-------
1|AB
2|CB
3|DF
4|EF
ID|Column 1|Column 2
--------------------
1|somedata|whatever1
4|somedate|whatever2
3|somedaty|whatever3
I would like to get:
ID|Name|Column 1|Column 2
-------------------------
1|AB |somedata|whatever1
2|CB | |
3|DF |somedaty|whatever2
4|EF |somedate|whatever3
INDEX works fast than VLOOKUP, I would recommend using that. It'll reduce the strain that many vlookups would put on your system.
First find the row that contains what you need in a helper column with MATCH:
=MATCH(A1,'mySheet'!$A:$A,0)
Then an INDEX using that number, that you can drag across and populate all your columns with:
=INDEX('mySheet'!B:B,$B1)
Your output would be akin to:
ID|Name|Match |Column 1 |Column 2
-------------------------
1|AB |Match1|IndexCol1|IndexCol2
2|CD |Match2|IndexCol1|IndexCol2
3|EF |Match3|IndexCol1|IndexCol2
Also! I'd recomend setting these ranges to actually cover the data, rather than referencing the whole column, for additional speed gains, e.g.:
=INDEX('mySheet'!B1:B100000,$B1)
I was thinking more on your problem, and if you have contorl over the data you're looking up on, I have another suggestion you could try.
In 'mysheet', where the raw data is kept, add in a new column that concatenates each column into one cell, with some sort of unique divider not in your data:
=B1&"+"&C1&"+"&D1&"+"&E1 etc...
Then you could do one VLOOKUP or INDEX/MATCH for each row, instead of 40.
Once you have it in your new sheet, you could split the results back out.
Splitting without formulas
Copy/Paste the results of the lookup formulas as Values in the next column.
Select that column, and in the Data tab on your ribbon, select Text to Columns.
Leave it on Delimited, hit Next. Uncheck Tab, check Other, and input your delimeter (+ in my example).
Click Finish.
Splitting with formulas
Use =FIND() to locate each delimter, and =MID() to pull out the text between each set of delimeters, using the previous delimeter as the Start_num.
Definitely the more complex of the two methods.
If I'm understanding correctly one thing I would do to start would be to use =VLOOKUP(A1;'mySheet'!$A:LastColumn;COLUMN(B1);FALSE). This way your column reference will move as you drag your Vlookup to the right.
No formula.No output. So there can't be a way to apply formula on 1 column only and get on the others.
The other feasible way is, put i formula in 1 cell, use $ signs inteligently and drag across all cells in a giffy without having to put vlookup 40 times.
Vlookup has 4 codes to input
1-Lookup Value. Use this $A1 (put $ on A and not 1)
2-Source data- Put $ signs everywhere
3-Column index no. Just above your entire data,in the 1st row,add an empty row.Put the values 1 in A1, 2 in B1, 3 in C1 and so on. Now in the formula,instead of manually putting "2" or "3" Give reference to these cells.Put $ on Numberal and not column ( B$1).
4- Type false or 0
Then drag this across everywhere.
Lookup Value. Use this $A1 (put $ on A and not 1)
Source data- Put $ signs everywhere
Column index no. Just use column name from where data needs to be pulled (e.g. COLUMN(B1) if Lookup value is in Column A and you want value from column B).
Type false or 0