I have a table in Excel which has the columns:
Date
Person Name
Amount (£)
The table is used to record when people pay me money. Typically, I can get more than one person paying me on the same day. Also, the same person will pay me on many days over the course of time.
Records are added to the bottom of the table so the ordering will be on date but no further ordering on name or amount.
Using formulas, is there a way I can retrieve the most recent amount for a specific person?
If this is too complicated or not possible then I can settle for the following work around:
Add a 4th column to the table called "Last". This will display TRUE if it is the last entry for a specific person, FALSE if it is not.
It felt like there should be a fairly straight-forward answer to this but I found it quite a head scratcher so was interested to see an answer.
Having done some googling I came across a solution posted on a dedicated excel site (view here). [NB - look under the header 'Arbitrary Lookups']
Applying it to your example, suppose your data is in A1:C10 and in cell D2 you want to type a name and return the most recent payment in cell D3:
1 Date Name Amt EnterName
2 20 Jul Bob 50 <enter name here>
3 13 Sep Susan 20 = enter formula here (see below)
4 06 Jan Xavier 100
In cell D3 enter the following as an array formula (i.e. type in formula and then press CTRL + SHIFT + ENTER
=INDEX($B$2:$C$10,SMALL(IF(OFFSET($B$2:$C$10,0,0,ROWS($B$2:$C$10),1)=$D$2, ROW(OFFSET($B$2:$C$10,0,0,ROWS($B$2:$C$10),1))-ROW(OFFSET($B$2:$C$10,0,0,1,1) )+1, ROW(OFFSET($B$2:$C$10,ROWS($B$2:$C$10)-1,0,1,1))+1),COUNTIF(OFFSET($B$2:$C$10,0,0,ROWS($B$2:$C$10),1),$D$2)),2)
It would recommend checking out the link I provided if you want more detail. For clarity, I have merely adapted the formula (changed cell references) from the link provided.
Here's one way to do it based on an answer I gave in a previous SO post.
=INDEX($C$1:$C$19,MATCH(MAX(IF($B$1:$B$19="PersonNameHere",$A$1:$A$19,0)),IF($B$1:$B$19="PersonNameHere",$A$1:$A$19,"")))
Where A is the Date column, B is the Person Name column, and C is the Amount column. You must enter this as an array formula by pressing Ctrl+Shift+Enter.
I can't see right here an easy way to do it in only one formula.
If you have your data from A2 to C11.
You can add this formula on the 4th column (let say in cell D2):
{=MAX(IF($B$2:$B$11=B2,$A$2:$A$11,0))}
This is an array formula you have to validate with Ctrl-Shift-Enter
This will tell you what is the last date for the current person.
And then find the last amount with another column (let say in cell E2) and use this formula:
=INDEX($C$2:$C$11,MATCH(D2,$A$2:$A$11,0))
[EDIT] I've just tried to combine the formulas into one and that simply works:
{=INDEX($C$2:$C$11,MATCH(MAX(IF($B$2:$B$11=B2,$A$2:$A$11,0)),$A$2:$A$11,0))}
and this is still an array formula.
Alas, #Excellll was smarter (and faster) and gave the solution at first shot
Related
I have a cell where I want to get the tax% based on a criteria
Coming from "Taxes", depends on manufacturer country, year of release and car type
I've tried to use search and index and its not working at all, I need the cell to check values in the manufacturer country, year of release and car type use these inputs go to the Taxes sheet and get the value
Before I start, I should come clean and say I am an evangelist for the OFFSET() function, and a mortal foe of INDIRECT().
Let's assume that the number of vehicle types (TRUCKS, SEDANS, ....) is the same for each country, ie 8. (If its not then that can be worked around with a bit more effort). You could put this number in a cell somewhere and use it when you need the number of types.
Also, let's say the first column in your screenshot is column A. And that the cell A1 contains "China".
Let's say we are looking for the tax rate in 2009, for SEDANS in France.
Function 1:
=MATCH("France",$A:$A,0) will return 14 (if I have counted correctly)
... ie cell A14 contains the word "France".
On the assumption that the years are the same for all countries we can use any of the header rows to find the right column.
Function 2:
=MATCH(2009,$3:$3,0)-1 will return 8 I think.
If your years are just strings of text, then replace 2009 with "2009".
Because your Types are not in the same order in each table (why?) we need an extra step.
Function 3:
=MATCH("SEDANS",OFFSET($A$1,(Result of f1) -1 + 3,0,8,1),0) should return 3.
What is the maths in the OFFSET function? I need to go down (14-1) rows from cell A1 to get to "France". From there I need to go down another 3 rows to get to the first of the list of Types, and there are 8 types to search in. I'm then looking at a range of cells which is 8 rows x 1 column.
Now you can extract your tax rate, using
Function 4:
=INDEX(OFFSET($A$1,(Result of f1) -1+3,1,8,100),(Result of f3),(Result of f2))
(I've put 100 as I don't know how many columns of years you have. You could use something like =COUNTA($3:$3)-1 if there was nothing else in the 3rd row after the last date).
I would put the results of each function in a cell while you test this. Once you are happy that each step is working correctly you can nest all the various functions together, or alternatively just put some extra columns on the right hand side of your results table, which you can Hide if you want to.
EDITED: To add some $ on cell references to lock the "origin" of the data.
If your tax tables are real Tables, each NAME'd with the name of the respective country, you can use something like:
=VLOOKUP(H13,INDIRECT(H12),MATCH(TEXT(H14,"0"),INDIRECT(H12 & "[#Headers]"),0))
where
H12 contains the name of the country
H13 contains the Type of vehicle
H14 contains the Year
eg:
You'll need to adapt this to your real ranges, but this provides an approach.
I'd suggest using dropdown lists (from Data Validation) in H13:H14 in order to avoid typos.
If you want to avoid using Tables and also the volatile functions OFFSET and INDIRECT (because if you have a lot of volatile functions they can impair performance of your worksheet) you can try the non-volatile, but longer and more obscure:
=VLOOKUP($H$13,INDEX($A:$A,MATCH($H$12,$A:$A,0)):INDEX($D:$D,LOOKUP(2,1/($A:$A<>""),ROW($A:$A))),$H$14-2000,FALSE)
In the above, you'll have to make adjustments
Assumptions are:
The country name is above the relevant tax table
Tax table starts in Column A
Change references to Column A if it does not start there.
Change the reference to Column D to the last column of your tax table (or even further if you will be expanding it).
The Year columns are labelled the same for all countries (eg: consecutive years starting at 2002)
$H$14-2000 calculates the column argument for the VLOOKUP function.
Can you please help with the above? Basically, i am trying to automate a list of names based on another persons name within an organization. I.e. John Smith being a manager, I want to return every person who is under John Smith. So, my formula is as below:
=IFERROR(INDEX(Sheet1!B:B,SMALL(IF(Sheet1!A:A=$AF$34,ROW(Sheet1!B:B)-MIN(ROW(Sheet1!B:B))+1),COLUMNS($AF$34:AF34))),"")
Sheet1!B:B is where the employees are and Sheet1!A:A is where the managers are. When i press control shift and enter, that works and returns the correct value. The problem is however, say I have 10 people under John Smith and the next manager is Dave T, the list will carry on and auto populate people under Dave when i want it to return the "" value provided in the IFERROR (presuming they are not under John Smith). To do this, i am adding +1 to:
...(Sheet1!B:B))+1),COLUMNS...
i.e.
...(Sheet1!B:B))+2),COLUMNS... ...(Sheet1!B:B))+3),COLUMNS...
This is driving me insane, can you please help?
Thanks, Colin.
Firstly, if at all possible it is best to avoid using entire columns for INDEX formulas for performance reasons, but if this is your only formula you should be fine.
Now as you are indexing the entire column, you shouldn't need to offset the row result (and in my example i start the index from row 1 so again no need to offset). In addition, you want to have the small update one step at a time, this is most commonly done with ROW(1:1) [Vertical dragging] or COLUMN(A:A) [horizontal dragging] your method also works but people are lazy and like to save characters:
=IFERROR(INDEX(Sheet1!B:B,SMALL(IF(Sheet1!A:A=$AF$34,ROW(Sheet1!B:B)
-MIN(ROW(Sheet1!B:B))+1),COLUMNS($AF$34:AF34))),"")
Essentially your formula will work for dragging horizontally but not for vertical dragging, it will always yield the first row number in the array...
=IFERROR(INDEX($B$1:$B$11,SMALL(IF($A$1:$A$11=$AF$34,ROW($B$1:$B$11)),ROW(1:1))),"")
Ctrl + Shift + Enter (formula bar)
Say we have:
In D2 enter the mane of the manager of interest. In C2 enter:
=IF($D$2=A2,1+MAX($C$1:C1),"")
and copy down:
The Helper column marks each subordinate with a unique seq. number.
Finally, in E2 enter:
=IFERROR(INDEX(B:B,MATCH(ROWS($1:1),C:C,0)),"")
and copy down:
NOTE:
By changing a single cell, D2, we can pick a different manager.
my question is pretty specific, and I haven't been able to find a solution. Here's a sample dataset that illustrates the problem:
First Last Sales Months
Kevin Smith $500 10
Joe Stevens $400 6
Frank Doe $600 4
I am looking for a solution that doesn't involve any computation columns or cells in the final result.
Now lets say I had this list
Kevin Smith
Frank Doe
I want to sum their sales/month in a separate cell.
I've tried:
=SUM(SUMIF(CONCATENATE(First, " ", Last),FullNames,Sales/Month))
Data is stored in rows 1-3 where column A is first name, Column B is last name, Column C is sales, and column D is months. The full names are in A5 and A6.
When I apply the function I have tried both Enter and Ctrl+Shift+Enter
Strangely enough, this formula works:
=SUM(SUMIF(First,FirstNameSubSet,Sales))
When I don't do any array concatenation or division in the formula.
Unfortunately, in my real life problem, I can't use this workaround.
I tried posting a picture, but even though I've been reading the answers on this site for a long time, I've never posted anything so I have no 'reputation.'
Thank you in advance for you help.
It would be a lot simpler if the full name were also in two separate cells. You could use a simple SUMIFS. But for the problem you present, if I understand it, given the following:
First is the named range containing the first names
Last is the named range containing the last names
Sales is the named range containing the Sales amounts
Month is the named range containing the number of months.
Fullnames is the named range containing the full name (combined first and last name)
Then the following array-entered formula (formula entered by holding down ctrl-shift while hitting enter) should produced the sales per month
=SUM(SUMIFS(Sales,First,LEFT(FullNames,FIND(" ",FullNames)-1),Last,MID(FullNames,FIND(" ",FullNames)+1,99)))
/SUM(SUMIFS(Months,First,LEFT(FullNames,FIND(" ",FullNames)-1),Last,MID(FullNames,FIND(" ",FullNames)+1,99)))
If you need the name comparisons to be case insensitive then change FIND to SEARCH in the formula.
Do you want the result to be all in one cell, or in one cell per row? If not, I am unsure why you are adding down a column (A1:A3).
As another note, if you are only avoiding computational cells/columns for appearance, you could put them on a separate sheet that is hidden.
I would've added this as a comment, but don't have enough reputation.
EDIT *
A JAN FEB MAR APR
1<drpdwn> A1+JAN A1+FEB A1+MAR A1+APR
what i need is for B1 to hold a formula that will take A1+B as a string and use this as the name of a Table to grab a value from. so something like
=INDIRECT($A1&"B")[[#Totals],[Column7]] so the cell will display the value in column 7 in the totals row for a table that is named the result of '=INDIRECT($A1&"C")' =B2&A3 also works for creating the variable, but again. unable to use in the above formula
Hopefully this is a little bit clearer
As an example, I will have 12 tabs that lets say are months, JAN FEB MAR etc... these are the column headers in my above.
Within these will be various Tables, like Expenditure, income, etc... they will be named ExpenditureJAN, ExpenditureFEB.
I want a simple (overview) tab, that lets me select expenditure in A1, and each months columns will use the formula to display a value from its relevant table, so A(JAN) would display jan's expenditure total etc.....
=ExpenditureJAN[[#Totals],[Column7]] this would work, but i need the expenditure bit, to change to what ever is selected from a picklist in A1.
***Old Question - Before edit -
Didn't know how to word the question, but here is my problem;
I have tables called AB, AC, AD, BB, BC etc...
I want to look up the following =AB[[#Totals],[Column7]] which works fine. However.....
I want it to change AB to be the string created from two cells so for instance =A3&B2[[#Totals],[Column7]]
Hopefully that makes sense, i am struggling to put this into words for some reason.... To add to this, A3 will be a drop down list, so the idea is, i change the value in A3 and it will change the table each cell the formula is in to look at the correct value.
B C D E
# #B #C #D #E
So # can change via a picklist, and the formula will detect this change and fire off to look at #totals, column 7 in the table #B/#C etc.. using the column headers and picklist as references for the table name.*
As user3514930 stated you want to use the INDIRECT function. Given the following table:
A B C D E
1<drpdwn> #B #C #D #E
If Cell B1 contains the formula =INDIRECT($A1&"B") it would show whatever is selected in cell A1 immediately followed by the character B. So drag that over to fill the rest of the row and update the trailing letter to =INDIRECT($A1&"C"), =INDIRECT($A1&"D"), =INDIRECT($A1&"E") etc. in the formulas.
Then when the dropdown box in cell A1 is changed, say to C the table would look like this:
A B C D E
1 C CB CC CD CE
Edit: So I got this to work like you wanted using INDEX, INDIRECT, and an additional cell to reference the table desired. I setup a table like you suggested named ExpendituresJAN. It had 6 columns, first was Week1-Week4, then HR, IT, Admin, Sales, and Payroll for departments, and then Column7 where I had totals per week. I threw in some random numbers (IT had a heck a week 3, spending nearly $997k evidently, and the sales department outdid itself with it's end of month party running over $10k, but those boys do love to party!). Sorry, where was I? Oh yes, example table, I added a Totals row on, and went to trying to figure it out because INDIRECT really seemed to be the key and I just had to wrap my head around things.
Next sheet had basically 4 cells with anything in them. A2 had a dropdown where I could Choose JAN, FEB, or MAR. B1 said JAN (I imagine C1 would say FEB, but I didn't go that far). B2 said #REF! a lot of the time.
________| JAN
<drpdwn>| #REF!
In the end A2 was moved down to A3 for my dropdown box, and row 2 was hidden, I'll get to why that is in a second. Ok, how to reference that... I can't seem to do it traditionally with structured reference, which is a pain, but there's got to be a way around it. I crack my knuckles, pull up Chrome, and practice a little Google-fu. Turns out what we needed was INDEX, which will return a cell or range from a table by name. B2 (hidden now) now contains the formula ="Expenditures"&A3 which, when JAN was selected read ExpendituresJAN. Excellent, I'm pretty sure we're most of the way there now. I just have to phrase my INDEX right and I'm set.
So, INDEX ended up being relatively simple all in all, but there's a catch. No #Totals row accessibility for INDEX. I got hung up on that for a few minutes until I stepped back and thought "wait, what's my totals row except a =SUM() formula? Ok, I can duplicate that. INDEX works with this syntax: INDEX(array/table, Row#, Col#) but you can use 0 for the row and it takes the entire row into account. Perfect for what I want, since I want a sum of Column7, I'll just wrap the INDEX in a SUM function.
=SUM(INDEX(INDIRECT(B2),0,7))
That spits back $1,036,371.00, the exact same thing my totals row shows for Column7. The only complication I could see is if your different tables have different Totals rows, as in one does a SUM, one does an AVG, and what not. Then the formula starts getting a bit more complex.
I'm trying to make a revision timetable for myself on Excel.
Let's say I'm doing four exams, A to D. Each exam has a certain number of "practice papers" that I have to do. Below is a demonstration table on Excel:
ExamName NoOfPapers
ExamA 4
ExamB 5
ExamC 7
ExamD 1
There is another table, with two columns: MonthDate and the paper I want to practice on that da. So,
May Paper?
1
2
.
.
.
29
I want to make it work so that if I put ExamA in the field under Paper?, it would automatically deduct 1 from the NoOfPapers of ExamA, to make it 3, so I make sure I'm not repeating the paper too many times.
If I only had 17 papers, it would have been easy to do it manually. But unfortunately I have 99 papers to do (exactly 99 :P).
How can I implement this on a cell as an IF statement (or any other possible way) on Microsoft Office Excel?
Thank you! :)
change the title of the column "NoOfPapers" to "OriginalNoOfPapers". Then create a column next to it called "NoOfPapersRemaining".
Assuming the cell with "ExamName" is A1, use the following formula in C2: =B2 - COUNTIF(Z:Z, A2)
(this also assumes that the column called "Paper?" is in column Z... in real life change it to the correct column on your spreadsheet.
I made four columns in row 1, Exam Name, Exam Total, Completed,Remaining. The completed column has the function
=Countif(B:B,A:A)
in roww 2, 3, 4, 5. The remaining columns are
D2="SUM(B2-C2)"
D3="SUM(B3,C3)"
D4="SUM(D4,C4)"
D5="SUM(D5,C5)"
In row 7 I have three columns, Date Complete, Exam Name, Paper. Exam Name must = The exact same as Cell A2:A5. All you would need is to enter the date and the exam name and it will show the total papers done and the remaining.
This can be better but does what I believe you asked. For instance, use of conditional formatting. If there is a deadline, add a column for the date and use conditional formatting to display an approaching deadline. Freeze row 7 to see remaining after entering a lot of dates in cell A8.
Hope this helps. I'm not a pro but like learning more about Excel.