I'm making a formula that looks up a value and returns a value, fairly simple procedure as I can use VLOOKUP or INDEX-MATCH. However, I cannot seem to create or find a way to make it work when the ranges are located side by side. (Will provide example)
I know I could move all the data into two columns, but that would make it Very long and the table is often looked at for reference. I would like to keep the table the way it is.
What I am looking for is that I can type the tank level(inches) into a cell and next to it it will return the tank level(gallons).
My current formula is
=INDEX('Calib. A & B'!$B$3:$B$47,MATCH(TANKS!$E$2,'Calib. A & B'!$A$3:$A$47,1))
Currently it compares cell E2 with A3:A47 and returns the corresponding value in B3:B47. It needs to search columns C, E, G, I, etc. Any ideas other than rearranging the spreadsheet?
There are different ways of obtaining the relevant rows/columns for the lookup:
=INDEX('Calib. A & B'!$A$3:$U$47,AGGREGATE(15,6,1/((TANKS!$E$2='Calib. A & B'!$A$3:$U$47))*ROW('Calib. A & B'!$A$3:$U$47)-2,1),AGGREGATE(15,6,1/(TANKS!$E$2='Calib. A & B'!$A$3:$U$47)*COLUMN('Calib. A & B'!$A$3:$U$47)+1,1))
The -2 for the rows argument of the index function is to adjust for the header position.
The +1 for the columns argument is to return the value one column to the right of the cell that matched.
This assumes, of course, that the values matching the lookup_value in E2 are only found in the "odd" columns of the data range.
As suggested by #TerryW, if your measure in E2 is not an exact match to the value in the data table (and the data table measurements are exact to the 1/8), you can roundup E2 to the next 1/8th.
Replace TANKS!$E$2 with ROUNDUP(TANKS!$E$2*8,0)/8
One way is with a long formula basically doing a union of results of the match on each column but having result as empty string when do not match it.
So we do a match against column A, if it doesn't find it it returns a blank string, if it finds it returns the number , then does the same for column C and concatenates the results and uses this on the index.
BUT this will only work if you search for an exact match.
For example:
=INDEX('Calib. A & B'!$B$3:$B$47,IF(ISNA(MATCH(TANKS!$E$2,'Calib. A & B'!$A$3:$A$47,0)),"",MATCH(TANKS!$E$2,'Calib. A & B'!$A$3:$A$47))&IF(ISNA(MATCH(MATCH(TANKS!$E$2,'Calib. A & B'!$C$3:$C$47,0)),"",MATCH(MATCH(TANKS!$E$2,'Calib. A & B'!$C$3:$C$47)))
You would need to add one more section for each column.
Related
I've spent a few hours on the web trying to find a solution for this with no joy.
Essentially I'm downloading my bank statement in to a spreadsheet. I want to categorise each expenditure by searching its text and seeing if it matches a range of keywords that I've manually added.
For example, Column A contains all my expenses and let's say cell A1 is "TESCO PS5 on 4th May"
I've set up a range of my own text cells in another column such as:
C3: MARKS
C4: COFFEE
C5: TESCO
C6: GREENS
Column D contains the following as categories of column C:
D3: Food
D4: Drink
D5: Food
D6: Fun
So in this example for A1 I want to add a formula to cell B1 that will search cells C3 to C6 and find the one that is contained within A1. Then it returns the corresponding value from column D.
So in this example, the formula in B1 would search A1, "TESCO PS5 on 4th May" and identify that the value in C5 "TESCO" is contained within A1. It then returns the associated value in D5, "Food"
Thus I'm able to categorise "TESCO PS5 on 4th May" as "Food"
If I use something like Match it seems to do the opposite of what I want. It lets me search for one string within a range of strings. I want the opposite. I want to search if a range of strings are within one string and identify the one that matches.
***************!!!!!!!!EDIT!!!!!!****************
SOLUTION FOUND. Adding it on here as having trouble with formatting using comments.
So I'm using this:
=IFERROR(ArrayFormula(INDIRECT("D"&2+MATCH(TRUE,ISNUMBER(SEARCH($C$3:$C$6,$A1)),0))))
SEARCH: search range for text I want to find in a single cell followed by the single cell I want to search.The result is either an error or an index of a matching search.
ArrayFormula: This allows SEARCH to work the opposite way to almost every example I found says it should be used.Instead of supplying a search term and a search range, instead I supply a range of search terms and specify one single cell to be matched against. ArrayForumla allows for multiple results to be output. It'll print those results one below the other in your spreadsheet. I don't actually want that but I can then use the two following functions to filter out undesired results:
ISNUMBER: Just identifies which result from your search was a valid match. Returns an int.
MATCH: This allows us to filter out all the non-results. Without this the spreadsheet will want to fill out multiple cells with useless data when using ArrayForumla. Using Match we are simply left with the one match result that matters, an index to the matched text field that is contained within our searched cell.
INDIRECT: allows us to build a cell index so we can reference the appropriate category cell data.
IFERROR: just makes sure the spreadsheet doesn't display errors for cells that it doesn't find a solution for.
In B1 write =VLOOKUP(A1, C3:D6, 2, TRUE).
You'll need to make sure that C3:D6 is sorted in ascending order by column C.
Info on VLOOKUP
As per you ranges I have created this macro. it works at my end. Let me know if you have any problem.
Sub TEST()
Dim i As Integer
i = Range("c65536").End(xlUp).Row
l = Range("a65536").End(xlUp).Row
For k = 1 To l
For Z = 3 To i
ck1 = Range("c" & Z).Value
If InStr(1, Range("a" & k).Value, ck1, vbTextCompare) >= 1 Then
Range("b" & k).Value = Range("d" & Z).Value
Exit For
End If
Next
Next
End Sub
You can try this in B1:
=INDEX($D$3:$D$6,SUMPRODUCT(--ISNUMBER(SEARCH($C$3:$C$6,$A1)),ROW($C$3:$C$6)-2))
Assuming that your list of categories (or keywords you search in A column) in between C3:C6.
And the corresponding value you want to add when each category/keyword found is between D3:D6
It's not elegant, and give you false result on empty cells, but it's a start.
So the following formula returns only the first value from the range. I kinda need all the matching search results indexed instead of just 1.
=Vlookup("*" & B3 & "*",A:A,1,0)
SPREADSHEET LINK
With Google Sheets use Query:
=QUERY(A:A,"select A where A contains """ & B3 &"""")
Since you have the Excel tag use this formula for excel:
=IFERROR(INDEX(A:A,AGGREGATE(15,6,ROW($A$2:INDEX(A:A,MATCH("ZZZ",A:A)))/(ISNUMBER(SEARCH($B$3,$A$2:INDEX(A:A,MATCH("ZZZ",A:A))))),ROW(1:1))),"")
Copy/drag it down sufficient for your needs.
Another option is
=FILTER(A2:A, SEARCH(B3, A2:A))
Filters out those values where the string can be found and also supports wildcards within the string or could be extended to match a regular expression instead.
vlookup is designed to always give you one result. Either your query matches then it will return the value, else it will return an error. As you want all the values I would recommend a different approach.
Create a column next to your column (in your case A:A) and fill it with your condition =IF($A1 = ("*" & B3 & "*", 1, 0). This column should be filled with 0 and 1 depending on the content of your column B.
Do whatever you want with the values in column A, and take your newly created column as condition. For example to sum all values in column A that match your condition: =SUMIFS(A:A, B:B, "=1")
I hope this helps to streamline your Excel. If you need further help maybe elaborate on the content of your columns A and B and what you want to achieve with your =vlookup().
I have an index match function that only needs 1 criteria, BUT there are potentially 5 different options for that single criteria. Is there a way to create the ability to go through the list of criteria iteratively until the match works outside of doing a series of nested if statements? I'm also hoping to avoid array formulas if possible because it slows down my workbook too much.
Current Concept being used:
=INDEX(Array 1,IFERROR(MATCH(a,Array 2,0),
IFERROR(MATCH(b,Array 2,0),
IFERROR(MATCH(c,Array 2,0),
IFERROR(MATCH(d,Array 2,0),MATCH(e,Array 2,0))))))
You formula works through a progression of possible MATCH functions and returns the first one in the series that does match. In this way, you will only ever get a single return or none at all.
If you were to put the a, b, c, d & e values into a constant array there would be the possibility of returning more than a single match but only one match can be returned back into the INDEX function that ultimately returns the value from Array_1. You need to pare out a single return using MIN, MAX, SMALL, LARGE, etc from the array of zero, one or many returns.
=INDEX(Array_1, MIN(INDEX(ROW($1:$5)+(Array_2<>{"a","b","c","d","e"})*1E+99, , )))
Please correct me if I misunderstood, I think you are looking to find the row number that matches 5 different criteria?
If so, you can do this:
=MATCH(A1 & B1 & C1 & D1 & E1, ArrayA & ArrayB & ArrayC & ArrayD & ArrayE, 0)
This will check for a match for all 5 values then return the row number. You can then index the value to find your match. Make sure when you enter the entire formula, use Ctrl-Shift-Enter instead of a normal Enter.
I understand that VLOOKUP searches the first column of a table in order to find a value, then it grabs the value from the same row and a different user-specified column. The following code returns data from the 2nd column, column B.
VLOOKUP(5,$A$2:B100,2)
Is there a way to set the return column to the last column of the input table? Something like the following, which would return data from columns B, P, and AC, respectively.
VLOOKUP(5,$A$2:B100,end)
VLOOKUP(5,$A$2:P100,end)
VLOOKUP(5,$A$2:AC100,end)
Alternatively, is there a way to grab the current column number and use that as an index?
VLOOKUP(5,$A$2:B100,current_column_number)
I'd like to write one VLOOKUP formula and then be able to drag it right across the spreadsheet, so that B100 becomes C100, D100, E100, etc. and the column lookup changes accordingly.
Update
I can do the alternate approach using the COLUMN function, but it requires programming a fixed offset and doesn't seem as robust. I'd still like to know if there is an "end" option.
=VLOOKUP(5,$A$2:B100,COLUMNS($A$2:B100))
Unfortunately you cannot simply drag it, you'll need to replace as there are two equivalent ranges written in the nested function.
The COLUMNS effectively counts the columns in the range giving the exact result needed for the VLOOKUP's end variant.
EDIT to show OP what a simple drag function would be like:
Function VLOOKUP2(Expected As Variant, Target As Range)
x = Target.Columns.Count
VLOOKUP2 = Application.WorksheetFunction.VLookup(Expected, Target, x)
End Function
You can use the Excel COLUMN() function to convert the column reference to a numerical index into the VLOOKUP table. Try this:
VLOOKUP(5, $A$2:B100, COLUMN(B2))
VLOOKUP(5, $A$2:P100, COLUMN(P2)
VLOOKUP(5, $A$2:AC100, COLUMN(AC2))
In pratice, you can just enter the first formula I gave above and then copy to the right. Each copy will automatically shift the column number to the end.
You could use the count function while holding ($) one side of the count range, thus giving you an integer that Vlookup can use.
Something like:
VLOOKUP(5,$A$2:B100,COUNT($A$2:A2))
You may need to add a + or - 1 to the count function depending on where your range starts.
It's effectively doing the same thing you already did with the array for the vlookup
Something I've wanted to do quite a bit lately, and can't work out how to do, is MATCH in a column I pass as an argument. Essentially, I have a two dimensional array, and I want to be able to find the first occurrence of a given value in the nth column, for any given value of n, and return the row number it occurs at. Alternatively (and more-or-less equivalently), I want to be able to search in the column with a given column header. Is there any way to do this?
Effectively, I want to simulate the non-existent function =MATCH(lookup_value,lookup_array,lookup_column,[match_type])
I've kludged together a horrible bodge job using INDIRECT, which works, but offends me horribly.
=MATCH(lookup_value,INDIRECT("R"&<top of array>&"C"&<left of array>+<column reference>&":R"&<bottom of array>&"C"&<left of array>+<column reference>,FALSE),FALSE)
This formula should work for you and will avoid INDIRECT. Anytime you can avoid using Indirect, I recommend doing so.
=MATCH(lookup_value,INDEX(lookup_array,0,MATCH(lookup_header,array_headers,0)),0)
If you aren't looking up the column by column header and just have the column number, then it becomes easier:
=MATCH(lookup_value,INDEX(lookup_array,0,column_number),0)
You could do something like this:
Set findCell = ActiveSheet.Range("A:Z").Find(What:="term_to_search")
Will select a header based on your search term.
Set range = ActiveSheet.Range(findCell, findCell.Offset(DEF_MAX_ROWS, 0))
Set up a range which will search from that header down a whole column.
For column references beyond Z you might switch notation (Excel Options, Formulas, Working with formulas and check R1C1 reference style) and, assuming the value to be looked up is in 'A1' (R1C1) with the column number in 'A2' (R2C1) apply:
=MATCH(R1C1,INDIRECT("C"&R2C1,0),0)
to save some complexity in converting a string of two or three characters into the relevant column number.
Say we have a two dimensional array: B3:E17 and we wish to locate Happiness in the third column of that array.In G1 enter:
B3:E17
In G2 enter:
3
In G3 enter:
=ADDRESS(ROW(INDIRECT(G1)),COLUMN(INDIRECT(G1))+$G$2-1) & ":" & ADDRESS(ROW(INDIRECT(G1))+ROWS(INDIRECT(G1))-1,COLUMN(INDIRECT(G1))+$G$2-1)
This will display the address of that third column. Then in G4 enter:
=MATCH("Happiness",INDIRECT(G3),0)
For example:
You can specify a range in a formula using the INDIRECT function. So, for example, if you put the letter designation for the column you want to search in cell A75, you could use:
=MATCH("Value_To_Match", INDIRECT(A75 & ":" & A75), 0)
So, if the value in A75 is G, the string built up in the INDIRECT call is G:G, and the MATCH will look through column G for "Value_To_Match" and return the row number in which it's found.
Using this idea, you can put a formula into A75 that generates the column designation for the column you want to search. For example, if your column headers are all in row 1, and the header you want to search for is in A74, you can do:
=CHAR(MATCH(A74, 1:1, 0) + 64)
using the CHAR function to convert numbers into ASCII characters, so 65 becomes A, 66 becomes B, etc. Note that this will only work if you don't have columns past Z. You'd need a more fussy formula to do the right thing with AA, etc.
You can overcome the annoyances of dealing with column letters by using R1C1 notation instead, which you can activate by adding a second parameter of FALSE to the INDIRECT expression. Now, instead of specifying your column by a letter, you'll specify it using a number. This simplifies the column-finder in A75:
=MATCH(A74, 1:1, 0)
and also the INDIRECT expression in your overall MATCH:
=MATCH("Value_To_Match", INDIRECT("C" & A75, FALSE), 0)