Excel Match, Offset, Index for multiple columns - excel

I want to find the value of corresponding clients PO # Invoice # Quote # etc.. & client list is mentioned in different multiple columns.
Formula used : =INDEX(D16,D17,2,MATCH('Client PO & Invoice Details'!A1:ACZ25,'Client PO & Invoice Details'!A1:ACZ1,0))
LOOKING FOR REQUIRED LOOKUP FUNCTIONS WITH MATCH OFFSET INDEX

The staging of your data is really inefficient. If you made a client number column and expanded the data vertically rather than horizontally, you could really save yourself a lot of headaches. For example, if your data was organized that way you could use a pivot tabel to massively simplify this problem.
Barring changes to your data structure, you can do a vlookup for the date against an offset range:
=VLOOKUP($D$17,OFFSET('Client PO & Invoice Details'!$A$1,0,MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0)-1,1048575,6),2,FALSE)
This formula should be placed in D18:D22 below the id and date filters. you will need to increment the vlookup index toward the end of the formula ( ...,2,FALSE) to grab the specific column you are looking for. The 2 will need to be updated to 3,4,5, and 6 in the subsequent formulas to get each of the values.
First The formula finds your client number in row 1, next the offset defines a range 6 columns wide starting at the column that the client number was found in, lastly the vlookup works as usual by finding the date in the first column of the offset range and returning the value of the indexed column.

INDEX(range you want to look in, how many rows down from the top of your range, how many columns to the right)
That is the basic usage for index. If the range is a single row or single column, then only the second entry is required and its how far down the range do you want to go. Another small caveat is if you 0 for # of rows or columns. 0 will make index return the entire corresponding row or column.
lets start by looking at what set of columns you want to be looking at. you need to match D16 (client#) with the appropriate entry in your header row. To do this, MATCH is a great choice.
=MATCH(value you are looking for, range you want to look in, and what type of match)
In your case
=MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0)
$1:$1 is the entire 1st row of the spread sheet. The $ will keep the row number from changing if the formula was copied up/down to another cell. The 0 at the end tells the function you want an exact match, and not an approximate type match. After performing this function you will know what column to start looking in.
So now you need to figure out what row you want to work with and then start pulling the data. This could be down with a VLOOKUP. You could define your range using an OFFSET function. I am however going to take a different route. I am going to use MATCH again to determine the row we want to look at based on the column we determined
=INDEX('Client PO & Invoice Details'$A:$ACZ,0,MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0))
This index is going to all rows in the column found with the match. So now we need to do a match in those results to figure out what row you are working with. In doing so we get a formula that looks like:
=MATCH($D$17,INDEX('Client PO & Invoice Details'$A:$ACZ,0,MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0)),0)
Now that you know the row you are working with and the column(S) you are working with you can now extract the data you need using INDEX.
In D18 place the following formula
=INDEX('Client PO & Invoice Details'$A:$ACZ,MATCH($D$17,INDEX('Client PO & Invoice Details'$A:$ACZ,0,MATCH($D$16,'Clent PO & Invoice Details'!$1:$1,0)),0),MATCH($D$16,'Client PO & Invoice Details'!$1:$1,0)+1)
In D19 use the same formula but change the +1 to +2. keep doing that as you go down increasing the +# by one each time.
Based on the comment you will add columns as clients are added, you will need to adjust the formula each time a client is added. There are ways to automated this, but you are probably better off going the offset route in this case.
Be aware that you do have a limited number of column to group clients by.

Related

Creating a dynamic formula so it takes a number within a cell as the row number

I have a master sheet, that holds all data in a matrix form (Criteria along the top i.e. Level 0,1,2,3,4,5) and criteria along the side (e.g. Organisation, Governance, Finance, Strategy). Within the master sheet, there is data that matches these criteria, and therefore plotted in the matrix. However, there is not data for all criteria, and therefore, there are blanks.
I would like to use this master sheet as the data source, and use the same format, but i would like to divide each section (I.e. Organisation, Governance, Finance, Strategy) into its own sheet and display the data for that criteria only.
I will also want to make this dynamic to ensure that if the criteria was changed in the future, the sheets would still work.
Therefore, I am using the following formula
=(UNIQUE(FILTER('MasterSheetGrid'!D8:I8,'MasterSheetGrid'!D8:I8<>"")))
This formula works well, however the row numbers are not dynamic and the formula may break in future. Therefore, i am wanting to use the following formula
=MATCH($C6,'MasterSheetGrid'!$C:$C,0)
to search for the row number, and then use this formula or output as the numerical row number in the formula above, but i receive an error each time.
>=(UNIQUE(FILTER('MasterSheetGrid'!D" &(MATCH($C8,'MasterSheetGrid'!$C:$C,0)& ":I" &(MATCH($C8,'MasterSheetGrid'!$C:$C,0)& ",'MasterSheetGrid'!D" &(MATCH($C8,'MasterSheetGrid'!$C:$C,0)& ":I" &(MATCH($C8,'MasterSheetGrid'!$C:$C,0)& "<>"")))
Can anyone help?
You can use:
INDEX('MasterSheetGrid'!D:I,MATCH($C6,'MasterSheetGrid'!$C:$C,0),0)
to get the desired row. So then something like:
=LET(DataRange,INDEX('MasterSheetGrid'!D:I,MATCH($C6,'MasterSheetGrid'!$C:$C,0),0),UNIQUE(FILTER(DataRange,dataRange<>""),TRUE))

Excel "SMALL" "IF" another row is not blank

I try not to ask for help like this but this one is screwing my noodle.
I have a costing spread sheet that I have managed to manipulate to give me a monthly cost role up (if exists) VS part number. Part numbers column c, months row 3.
On another sheet I'm trying to list the part numbers next to the cost role up and relevant date (each part number may have multiple entries)
I just need to do a "SMALL" for the "date" row (Row 3) on my costing sheet "IF" the "correct part number row" (or a fresh MATCH/VLOOKUP for the part number) has data in it. Or some how have the small return the Column INDEX number. I could then use INDEX to return the correct date and value using SMALL and Column B (the number of costs per part number, so if there are 3 instances that column currently list 1,2,3 before starting the next part number)
So close..... but this last bit is a struggle. Its a shame SMALL cant return INDEX Column numbers.
Does anyone know how to get a "SMALL" to lookup a row (based on a column search criteria) and check if the column has data, if so include the that column header in the "SMALL"
Update...
Thanks for your comments. I've stripped out the problem into a separate sheet to make it a little clearer. (I'll upload if possible).
I've also completed the rest of the excel to show the whole process. In doing so I've discovered Headers are automatically converted to text and so added a column to work around this using "DATEVALUE".
The goal is to list the number of costs related to a part number so.... if 500111 has had a cost role up in 3 different months it will list them in the cost report. So.... part number, relevant column "date" from "Cost data" sheet and relevant cost (#that part number # that date). if I can get a list of dates from "Cost Data" columns and put them in Column D "Costing date (text)" next to the relevant part number i should be sorted. I've highlighted the column in red on the new screen shots.
Cost Report
Cost Data
lines highlighted in yellow just to show they are empty
Edit:
Almost there for anyone else trying this
=INDEX($B$5:$J$5,,SMALL(IF($B$6:$J$6>0,COLUMN($B$6:$J$6)),3))
I just need to figure out how to define a variable "ROW" within a SMALL(IF statement. I should then be able to reference the correct table row number (which I already have).
Anyone know how to put a variable ROW or COLUMN reference in a SMALL formula?
Did not understand the problem fully.
But like this you can have a variable Row in the small formula:
=SMALL($A$4:$A$10;ROWS($C$4:C4))

"Get Unique Values" formula adds a row of "0"'s to the end of the table

I was trying to implement this formula into my book to condense a larger table into a list format. I cannot use pivot tables because I need to do complicated calculations in later columns after I have achieved this condensed list.
The table looks like:
The Row# Column is filled by an Array Formula:
{=IFERROR(MATCH(0,COUNTIF(INDIRECT("$F$1:$F$" & ROW(E3)-1),$A$1:$A$4000),0),"")}
which translates to: "Get the row # of the first item in column A that isnt found in Column F above my current position"
The other three columns are filled by: =IFERROR(INDIRECT("A" & $E2),"")
My problem is that the last row of the table is always filled with 0,0,0 because for some unknown reason it matches the first blank row as a unique value.
My question is: How do I add a criteria that the unique value is not blank or 0?
As for clamping the search range, the table is generated by a program and has a variable and unknown number of rows so I cannot manually set the table range to the last non-blank row. I put $A$1:$A$4000 so that I won't miss any of the table's entries.
If there is a way to automatically determine the last row, that would also solve the problem.
Edit: I also realize that the list is not being condensed properly, I'm working towards getting it to compare all three values instead of just the first value.
Edit2: I got it to compare all three values, but the 0,0,0 problem is still there if anyone has ideas about that.
{=IFERROR(MATCH(0,COUNTIF(INDIRECT("$F$1:$F$" & ROW(E2)-1),$A$1:$A$4000)*COUNTIF(INDIRECT("$G$1:$G$" & ROW(E2)-1),$B$1:$B$4000)*COUNTIF(INDIRECT("$H$1:$H$" & ROW(E2)-1),$C$1:$C$4000),0),"")}
Since you are dealing with Excel 2007, and want a table of unique values, I suggest the Advanced Filter.
Setup your Data as a Table
Navigate to the worksheet where you want the results of the "filter"
Then Data=>Advanced Filter
Voila!
If you have more than three columns, but you only want to apply the unique filter on the first three, you can use a formula for the filter criteria.
For example:
A1: Unique Formula
A2: =COUNTIFS($A$7:$A7,$A7,$B$7:$B7,$B7,$C$7:C7,$C7)=1
you can visualize the effects of this filter by entering it into some helper column, adjacent to the table in row7, and then filling down the length of the table. If you did this, you could use the autofilter, and just filter on 1
Voila!

Want a named list with non-continuous cells

I thought this should be a common thing but my search has not returned anything meaningful. I'd prefer an Excel solution, rather than VBA.
I have a proposal sheet with details like number (col D), date etc and a column saying if the proposal got converted (to business).
On the invoice sheet, I have a list of invoices. The requirement is to always refer the proposal number against which this invoice is being raised. For removing human error, the applicable proposal numbers should be available as a drop down. Hence the drop down should only show the proposal numbers against which the invoice can be issued (proposal got converted to business).
This means that non-continuous cells (say, D3, D4, D6, and D10 - where proposal converted is 'yes') from the proposal sheet should be the values available in drop down of data validation in the invoice sheet. How do I achieve this?
Edit:
Adding an image that is representative of the 2 sheets.
My solution involves creating a list using the INDEX MATCH or INDEX SMALL method to pull multiple results from the data that can be used for the dropdown.
I added a couple of extra columns to count the number of times an invoice has been invoiced and then a further Yes/No to make the index formula easier to follow. You'll see that my example only has 2 values to select from as the others have been fully invoiced.
The scary formula in Q1
=IFERROR(INDEX($A$2:$H$1000,SMALL(IF(($H$2:$H$1000="Yes"),ROW($A$2:$H$1000)-1),ROW(1:1)),1),"")
This is an array formula so you must use SHIFTCTRLENTER instead of just ENTER in the formula bar. {} backets will be added if you do it right.
To break it down, INDEX($A$2:$H$1000 is selecting your proposal data and some more rows below (1000). SMALL(IF(($H$2:$H$1000="Yes") is looking at my extra Yes/No column for "Yes". ROW($A$2:$H$1000)-1) is returning the row number minus 1 to account for the fact that our range starts at A2. ROW(1:1) is saying that we want first match in the list and the ),1) returns the vlue in the first column of the range $A$2:$H$1000.
Because ROW(1:1) returns the first result, you will need to autofill down in order to pull more results. As you do this the formula will copy down as 1:1, 2:2, 3:3...ect. I filled down to row 50 to allow for a decent amount of results.
You could set your validation range to Q1:Q50 but then you would have lots of empty space in your dropdown so, have a look at cell R1.
="Q1:Q" & COUNTA(Q1:Q50)-COUNTBLANK(Q1:Q50)
This formula creates a range based on the results in column Q. You can use that value in the data validation range by entering.
=INDIRECT($R$1)
Thus creating the dynamic range that you require.
You don't have to use the extra columns that I added but the formulas are;
=COUNTIF(M2:M1000,A2) to count the number invoiced
=IF(AND(F2="Yes",G2<E2),"Yes","No") to check if it can still be invoiced.
if you do want to use them then I'd recommend formatting your data as a table so that the formulas are copied down automatically on new rows.
Also I'd advise putting the index list on a different sheet so that rows are not deletes etc.

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.

Resources