complicated index/match with multiple columns and rows - excel-formula

I have a complicated lookup that has 2 criteria, the issue is that the 2nd criteria is dependent on the location of the first and I am having trouble understanding how to feed it the location from the first match.
Criteria 1 is easy it is family size and it basically reads from one column and matches the family size
Criteria 2 is income amount, the income table is 4 columns wide and 8 rows deep (C5:F12). The income amount varies depending on family size. So I need to return the value that closest matches the income for that family size without surpassing the number. IN the example below the income provided is $55,200 for a family size of 4 should return E8 ($62,950).
Once I have that I then have to write another formula to return the award amount which is on row 4. In the example provided the award amount would be cell E4 ($70,000). I have no clue what formula I would use for this; maybe a long IF statement (not sure).
I am using this formula but am getting the #N/A error which is likely because of the size of the lookup array. Every example I’ve seen on index/match has the columns to lookup the value in one row but with my data the row that needs to be looked in is dependent on the family size.
=INDEX(C5:F12,MATCH(C14,B5:B12,0),MATCH(C15,C5:F12,-1))

You do not need the intermediate step. Just use:
=INDEX($C$4:$F$4,MATCH($C$15,INDEX($C$5:$F$12,MATCH($C$14,$B$5:$B$12,0),0),-1))
If you want the other value put this formula in C17:
=INDEX($C$5:$F$12,MATCH($C$14,$B$5:$B$12,0),MATCH($C$15,INDEX($C$5:$F$12,MATCH($C$14,$B$5:$B$12,0),0),-1))
These formula work independent of each other.

Related

Excel Match to Table Header from three criteria

I am trying pull a rank value (UN, NI, AE, HE, EX) from table headers, when individual score is compared to the table of goals. The Match criteria must include level and quarter, as the goals increase each quarter and goal ranges are different per individual's level.
I have tried xlookup, but I cant get it to work has #value! error
=XLOOKUP(B2&E2&D3,Goals[[ Level]]&Goals[Quarter]&Goals[[UN]:[EX]],Goals[[#Headers],[UN]:[EX]])
I have tried index match combination, but could not figure out a proper formula for the 3 criteria. I did not get it to work, and I did not get it to include a 3rd match criteria either.
=INDEX(Goals[[#Headers],[UN]:[EX]],,MATCH(D3,INDEX(B8:F11,MATCH(B2,A8:A11,0),,),-1),)
The goal is to fill in cell B4 with the equivalent ranking value which equates to the the headers in cells B7:F7. If person's score is equal to or greater than a level and quarter goal then they should get a ranking matching that column's header as long as it is not greater than the next column's goal.
You need two XLOOKUP calls, one to pick the row and then one to match the column. Try this.
=XLOOKUP(D3,XLOOKUP(B2&E2,Goals[Level]&Goals[Quarter],Goals[[UN]:[EX]]),Goals[[#Headers],[UN]:[EX]],"",-1)

VBA code required to loop through different sized rows of data and return MAX value

I am currently automating a dashboard creation and I've hit a bit of a roadblock. I need some code that will go through about 7000 rows of data and return the highest value in a certain column for each specific item. The data is copied from a pivot table and so is broken down into row sections, I have attached a mock of what it looks like.
I need the highest value in Column G for each portfolio, and will need to use the portfolio code (e.g. XY12345 - They are always 7 characters) to map that value to the dashboard.
My issue is, each portfolio has a different number of rows for the values, and some have blank cells between them, and therefore I am stumped. I was hoping to use Column J to count the number of rows for each portfolio (as there are no breaks for the portfolios in this column) and then use a loop to loop through each portfolios rows of values, based off the Column J count, and then return the highest row value for each portfolio. Problem is I'm new to VBA and have been teaching myself as I go, and I've yet to use a loop.
Many thanks,
Harry
If I understand correctly, you're looking for the largest value in Column G.
I'm not sure why you think you would need VBA for this.
Get the maximum value of a column
You mentioned that you're concerned about each column not having the same number of cells but that's irrelevant. as SUM ignores blank cells, so just "go long", or - find the maximum of the entire column.
To return the largest number in Column G you could use worksheet formula :
=MAX(G:G)
The only catch is that you can't place that formula anywhere column G or else it would create a circular cell reference (trying to infinitely add a number to itself). let's pit that formula in cell F1 for now (but anywhere besides column G would do fine).
Find the location of a value
Now that you know the largest value, you can determine where it is using a lookup function such as MATCH or VLOOKUP. Like with so many things in Excel, there are several ways to accomplish the same thing. I'll go with MATCH.
Replace the formula from above (in F1) with:
=MATCH(MAX(G:G),G:G,0)
This will return the row number of the first exact match of the maximum value of Column G.
As for the third part of question: returning the code like X12345 where the value exists, will be a little tricky since your data is not organized in a logical tabular style (tabular meaning, "like a table").
Your data is organized for humans to look at, not for machines to easily read and manipulate it. (See: Office Support: Guidelines for organizing and formatting data on a worksheet)
Basically, when organizing data in rows, all relevant information should be on the same row (not a subjective number of rows behind). Also, you have the number combined with other information.
My suggestion for a quick fix:
Right-click the heading of Column C and choose Insert to insert a blank column.
In C2 enter formula: =IF(B2="",C1,LEFT(B2,7))
Copy cell C2
Select cells in column C all the way to the "end" of your data, where ever that is (not the end of the worksheet). For example maybe you would select cells B2:B1000)
Paste the copied cell into all those cells.
Now, you can again modify the formula in F1:
=INDEX(C:C,MATCH(MAX(G:G),G:G,0))
This will return the value from Column C in the same row that the maximum value of Column G is located.
This is known as an INDEX/MATCH formula.
Hopefully this works for you in the interim until you can organize your data more logically. There's lots of related information and tutorials online.

advanced filter w/ 1 row above

UPDATE - this was resolved with:
=OR(ISNUMBER(SEARCH("225522",A2)),ISNUMBER(SEARCH("225522",A‌​3)))
As an advanced filter criteria.
The goal was to find 225522 on the second row, and pull the row above it which was accomplished with the above along with the row containing 225522.
Original question
I have several thousand lines on an excel sheet and each second line has a header line labelled USD. I need to filter to find all of the 225522 rows but I need to include the row above it with the USD.
Example:
USD
11111.222222.333
USD
11111.225522.333
USD
11111.222222.333
USD
11111.222222.333
USD
11111.225522.333
I can filter 225522 and usd, but that would just unfilter all of the rows with 222222 leaving me to manually delete thousands of USD rows. It looks like the below...
USD
USD
11111.225522.333
USD
USD
USD
11111.225522.333
But I need it to look like
USD
11111.225522.333
USD
11111.225522.333
Is there a way to filter 225522 and keep the row above it to achieve my example above?
Use an advanced filter with formula criteria like:
=OR(ISNUMBER(SEARCH("225522",A2)),ISNUMBER(SEARCH("225522",A‌​3)))
where A2 is the first row of data in the relevant column and A3 is the second row.
This is may or may not fit your definition of filter.
In an unused portion of your sheet or in a new sheet use the forllowing formula assuming that your data is in the range A3:A2003
=AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),ROW(A1))
That will generate a list of row numbers that match your criteria. What you want to do now is have ROW(A1), increase by 1 every two rows it gets copied down. Then you will want to put an if statement in that so that if ROW(A1) is odd, your use the row number -1 to get your USD. and if even that you leave the row number alone. Now tie that in with INDEX and you will generate the list you are looking for.
so to get it to count every second row increasing by 1 we could use something like:
=INT((ROW(A1)+1)/2)
This would turn our formula into:
=AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),INT((ROW(A1)+1)/2))
in order to get our -1 to the row number we could incorporate something like:
=-ISODD(ROW(A1))
incorporating that into the previous formula would result in:
=AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),INT((ROW(A1)+1)/2))-ISODD(ROW(A1))
The above could also have been achieved with an if statement but I decided to take a short cut.
The last step will be to incorporate it into an INDEX formula. which will wind up looking like:
=INDEX($A:$A,AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),INT((ROW(A1)+1)/2))-ISODD(ROW(A1)))
Now you have the formula, you just need to copy it down as far as you need to go. It will start spewing errors when you run out of acceptable rows.
Alternatively you can set it up to display "" when there is an error/it runs out of rows by using the following:
=IFERROR(INDEX($A:$A,AGGREGATE(15,6,ROW($A$3:$A$2003)/ISNUMBER(SEARCH("22522",$A$3:$A$2003)),INT((ROW(A1)+1)/2))-ISODD(ROW(A1))),"")
The draw back to this method is that it performs array like calculations. As such you should limit its use to a defined range and not full column references within the AGGREGATE function. Having said that the Advanced filter option listed in your comments seems much simpler and probably a hell of a lot faster.
UPDATE
Since you need to pull multiple columns, I would adjust your INDEX portion of the formula. Now assuming your criteria column (column where the 225522 is located) is column F I would modify your formula as follows:
=IFERROR(INDEX($F:$F,AGGREGATE(15,6,ROW($F$2:$F$4401)/ISNUMB‌​ER(SEARCH("225222",$‌​F$2:$F$4401)),INT((R‌​OW(A1)+1)/2))-ISODD(‌​ROW(A1))),"")
Now in order to return the same row but different columns there are two ways to approach this. Either change the $F:$F to the appropriate column for each column you want to return or change the range from F:F to F:P and add a column reference to the index. This following method works if the 11 columns are side by side. Other wise you will either have to assign a manual column reference that covers your range or use a match function to match column headers over the same range.
=IFERROR(INDEX($F:$P,AGGREGATE(15,6,ROW($F$2:$F$4401)/ISNUMB‌​ER(SEARCH("225222",$‌​F$2:$F$4401)),INT((R‌​OW(A1)+1)/2))-ISODD(‌​ROW(A1)),COLUMN(A1)),"")
The reason you see me using A1 with ROW() or COLUMN() is that I am using it as a counter that starts at 1. So no real harm leaving it at F1 for row references as it is really only important that the row start at 1. conversely COLUMN(A1) can really be any row from column A as I am only interested in starting at 1. If you have to manually index because your columns are not side by side, replace COLUMN(A1) with an integer that represents the column number you want starting from the first column reference in the index range. So in the case of the formula above F:P, start counting from F.

For dates with missing data, take average of values from closest dates

I have sporadically collected data for stream nitrogen levels. For dates where nitrogen levels are not available, I'm hoping I can use an Excel formula that will estimate the value by calculating the average of nitrogen levels from the two closest dates.Note that nitrogen is not correlated with flow (or other water quality parameters) and there is no trend so I can't use a regression equation to estimate values.
Below is an example of what the table looks like for columns A, B, and C, and rows 1 (header) to 7. Column B contains the real data (note that I inserted 'no value' for illustrative purposes). Column C is what I would like to have calculated. Because I have thousands of rows of data, manually entering each of these formulas is not an option.
Date_______Actual Value______Desired Calculation
1/1/2012_______0.15__________=B2
1/2/2012_____[no value]_______=AVERAGE(B2,B5)
1/3/2012_____[no value]_______=AVERAGE(B2,B5)
1/4/2012_______0.17__________=B5
1/5/2012_____[no value]_______=AVERAGE(B5,B7)
1/6/2012_______0.23__________=B7
=IF(B1<>"",B1,VLOOKUP(MAX($A$1:$A$4),$A$1:$B$4,2,0))
Misread the question the first time.
Test to see if B1 is equal to "" or not. If it is empty then perform the VLOOKUP searching for the max value of column A (most recent date), and then use the value for the adjacent column (2).
This will not cover the case where the most recent Date has no value in column B. I will return "" in that case.
TREND Option
Based on your comments and the use of some helper cells you could do the following. Make a small table off to the right somewhere of just your known dates and your known values from B. We can populate this table using the following formulas. Let arbitrarily put this table in columns F and G.
in F2 use:
=IFERROR(INDEX($A$2:$A$1564,AGGREGATE(15,6,(ROW($B$2:$B$1564)-ROW($A$2)+1)/($B$2:$B$1564<>""),ROWS(B$2:B2))),"")
This will pull the dates in order that they appear with values in B that are not "". Then in G2 put the following formula in which will pull the associated value from B
=IFERROR(INDEX($B$2:$B$1564,AGGREGATE(15,6,(ROW($B$2:$B$1564)-ROW($B$2)+1)/($B$2:$B$1564<>""),ROWS(B$2:B2))),"")
Both those formulas are currently set up to work with a header row and data starting in row 2.
once we have the helper table set up, you can set up a TREND function, which is a line of best fit through all your known points. You can pick the point on this line for dates with no value in B. In C2 you would add:
=IF(B2="",TREND($G$2:$G$3,$F$2:$F$3,A2),B2)
you would copy this formula down. It checks to see if B is blank. If it is then it pulls a value for B from the trend line. If it is not blank, then it will use the value in B.
AVERAGE Option
Again using the helper table in the same spot. This one gets a little uglier. In C2 place the following and copy down
=IF(B2<>"",B2,IF($A2<$F$2,$G$2,IF($A2>$F$3,$G$3,(INDEX($G$2:$G$3,IFERROR(MATCH($A2,$F$2:$F$3,1),1))+INDEX($G$2:$G$3,IFERROR(MATCH($A2,$F$2:$F$3,1)+1,2)))/2)))
The first thing it does is check for a blank value in B. If there is no blank then it uses the value in B2. If there is no value in B2 it then proceeds to check the date of the blank against the first date in your helper table. If it is less than that first value, it uses the first value of B since there is nothing to average it with. I then proceeds to do the same to see if the date exceeds the last value in the table. (this is currently hard coded). If it exceeds the last date in the table it uses the last value for B. the last option for the date is for it to be in the table. It take the average between the date prior to the date and question and the next date with a value.
Optional version where you dont have to hard code the last values of helper table, but you still need to hard code the range of the helper table to meet your needs.
=IF(B3<>"",B3,IF($A3<$F$2,$G$2,IF($A3>MAX($F$2:$F$3),VLOOKUP(MAX($F$2:$F$3),$F$2:$G$3,2,0),(INDEX($G$2:$G$3,IFERROR(MATCH($A3,$F$2:$F$3,1),1))+INDEX($G$2:$G$3,IFERROR(MATCH($A3,$F$2:$F$3,1)+1,2)))/2)))
TREND Between only two points
So I adjusted the formula a bit on this one. Its kind of a mix of the trend and previous options listed above. I also made it automatically selecting the end values of your table, so now you just have to copy your table down as far as you need. Its also works on the premise that only your data value in B are present, no numbers below your last row.
=IF($A2<$F$2,$G$2,IF($A2>=MAX(OFFSET($F$2,0,0,COUNT(B:B),1)),VLOOKUP(MAX(OFFSET($F$2,0,0,COUNT(B:B),1)),OFFSET($F$2,0,0,COUNT(B:B),2),2,0),TREND(OFFSET($F$2,IFERROR(MATCH($A2,OFFSET($F$2,0,0,COUNT(B:B),1),1),0)-1,1,2,1),OFFSET($F$2,IFERROR(MATCH($A2,OFFSET($F$2,0,0,COUNT(B:B),1),1)-1,0),0,2,1),$A2)))
So basically TREND function is a line of best fit through known points. if your know points do not all sit in a straight line it figures out what straight line passes near them minimizing the distance they are from the line. If we limit the points it using to make its line to only 2 points, then the line has to pass through those two points. Remember, the helper table is a list of all known points.
So basically what the formula doing is checking to see if the date is less than or equal to the first known point on the helper table. If it is, use the value from the first known point in the table. If its not, check to see if the date is greater than the last date in the table, if it is lookup the last known date in the table and return the corresponding table. If neither of these cases is true then the date must be in the table. That means we can get two points from the table and their corresponding values to use in the trend function. We feed the TREND function a an array of 2 known X and 2 Know Y values, and then supply it with an X value we are interested in. In this case X would be the dates, and Y would be the values in the second column.
Revised Helper table
In F2 use this formula:
=IFERROR(INDEX(OFFSET($A$2,0,0,COUNT(A:A),1),AGGREGATE(15,6,(ROW(OFFSET($A$2,0,1,COUNT(A:A),1))-ROW($A$2)+1)/(OFFSET($A$2,0,1,COUNT(A:A),1)<>""),ROWS(B$2:B2))),"")
and G2 use this formula:
=IF(F2="","",INDEX(OFFSET($A$2,0,1,COUNT(A:A),1),MATCH(F2,OFFSET($A$2,0,0,COUNT(A:A),1),0)))
and if you want to verify how far down you want to copy your helper table, you can put this in lets say I3:
=COUNT(B:B)+1
Now these update that are using the count(A:A) or B:B require that no other numbers be above or below your data in the A or B column.
UPDATED Average
I also tweaked the average formula to give this option as well.
=IF($B2<>"",$B2,IF($A2<=$F$2,$G$2,IF($A2>=MAX(OFFSET($F$2,0,0,COUNT($B:$B),1)),VLOOKUP(MAX(OFFSET($F$2,0,0,COUNT($B:$B),1)),OFFSET($F$2,0,0,COUNT($B:$B),2),2,0),AVERAGE(OFFSET($F$2,IFERROR(MATCH($A2,OFFSET($F$2,0,0,COUNT($B:$B),1),1),0)-1,1,2,1)))))
Example results (note rows 14-69 have been hidden so you can see what is happening around row 75.

Lookup or If Condition Formula in MS Excel [duplicate]

This question already has answers here:
Two column lookup in table array using INDEX and MATCH
(2 answers)
Closed 7 years ago.
I need some help for a lookup formula in excel sheet. I am basically trying to find out a corresponding value of for a row, where two conditions in the same row meet. Let me illustrate it his way. If within the range of column A a certain value is found and in the same row but in Column C other certain value is equal then return the value in Column B for the same row.
The table is as follows:
Column A Column B Column C
---------------------------------------------------------
Ahmadaba Irrigation 550,041
Ahmadaba Livelihood 18,890
Ahmadaba Power 233,694
Ahmadaba Public Building 64,707
Ahmadaba Rural Development 104,381
Ahmadaba Transport 1,044,644
Ahmadaba Water Supply & Sanitation 1,156,322
To elaborate; in reference to above table if Column A is equal to Ahmadaba and Column C is equal to 18,890 then I should get the value Livelihood from column B.
By far the least resource-heavy (and therefore most efficient) set-up would be to use one additional column within your table in which to generate a series of unique identifiers based on the entries in columns A and C.
So if your table is currently in, for example, A1:C8 (with headers in row 1), then you could use column D to this end, entering this formula in D2:
=A2&"|"&C2
(The separator is probably not strictly necessary in your case, though in general it is good practice.)
and copied down to D8.
After which, and assuming your chosen search values, e.g. "Ahmadaba" and "18,890" are in E1 and F1 respectively, the required formula is:
=INDEX(B2:B8,MATCH(E1&"|"&F1,D2:D8,0))
Note that one of the advantages of this set-up is that you can also employ a more flexible variation of the above which references not just 8 rows but an entire column's worth, viz:
=INDEX(B:B,MATCH(E1&"|"&F1,D:D,0))
with virtually no detriment to calculation performance.
If, for whatever reason, you cannot use an additional column within your table to perform these concatenations, then an alternative solution would be:
=LOOKUP(1,0/((A2:A8=E1)*(C2:C8=F1)),B2:B8)
However, it should be pointed out that, with this set-up, the amount of calculation Excel has to perform is directly proportional to the size of the range being referenced. As such, unlike with the INDEX/MATCH construction, it would be a disastrous idea here to use:
=LOOKUP(1,0/((A:A=E1)*(C:C=F1)),B:B)
which is forcing Excel to calculate more than 2 million cells.
Regards

Resources