VLOOKUP is a powerful and much-used Excel function. If you’re not familiar, it finds a lookup value in a table and returns the corresponding value of another column. This is great for looking up information by reference. In the example image above, Name is the lookup value, and it returns the matching Salary. If you are a power Excel user, you are likely very familiar with this function. If not, here’s how it works:

- =VLOOKUP(
*Lookup_value*,*Table_array*,*Col_index_num, Range_lookup*))**Lookup_value –**The value you want to find in the lookup value column**Lookup_value –**The table range containing columns for both the lookup and return values**Col_index_num –**The index number for the column containing the return values**Range_lookup –**The type of match: Nearest Less Than (TRUE), or Exact (FALSE)*[optional]*

VLOOKUP, though powerful and useful, is not without its limitations. In fact, it can be dangerous because of some unexpected effects and behaviors. If you use VLOOKUP, please read on to learn about these issues. This equally applies to VLOOKUP’s sister function HLOOKUP (which does horizontal lookups instead of vertical lookups) and another similar function, LOOKUP. I have provided a safer and more flexible alternative lookup method, which I use virtually everywhere in place of VLOOKUP.

First, I’ll explain some of VLOOKUP’s limitations:

*Your data range is limited to a table*. That means the data you are looking up has to be in a standard tabular form. You cannot use VLOOKUP to find a lookup value in a different table, sheet, or offset row. This limits the ways you can display your data, as anything you want to lookup must be available in a standard table format in your spreadsheet.*VLOOKUP always searches the leftmost column of the specified table to find the lookup value.*Again, this limits your choices in presenting data as lookup values always have to be to the left of the return values. This sometimes means you must have multiple copies of tables in order, think far ahead when creating tables that might be used in lookup, or reorder columns after the fact simply to use VLOOKUP.*You can only specify the return value column by index number.*This means there is no way to include a static reference to the return value column. If someone adds a column between the lookup value column and return value column, it will break your VLOOKUP and you have to manually increase the column index number in the formulas. This is a maintenance nightmare.*VLOOKUP provides a very limited approximate match feature*. The only aproximate match option finds the nearest “less than” value. Unless you want that type of behavior, you’re out of luck and can’t use it.

Now, here are some dangers of VLOOKUP:

*By default, VLOOKUP uses approximate match.*If this is how you want it to function, then great… However, in many cases you want an exact value returned. It gives no indication it is picking a closest match result. If you do not want this behavior (which is most of the time, I have found…), you remember to explicitly set the Range_lookup argument in the formula to FALSE. Range_lookup is optional, and not a very descrive name of this feature, so it is often overlooked. This quirk is exasperated by the second danger…*VLOOKUP can provide false results if the table is not sorted in ascending order!*This is an issue when you use the approximate match feature, which is TRUE by default. Basically, VLOOKUP starts at the top of the table and goes down row by row until to gets to a valie less than or equal to the lookup value. If your table is not sorted in ascending order, this can give false results, as the formula stops processing rows immediately after finding a “match.”

Sufficiently scared? Checking your spreadsheets for issues now?? The answer to these problems and limitations is the INDEX-MATCH lookup method. This methods uses two functions together to provide a more safe and flexible lookup feature. Here’s how each function works, independently:

- INDEX returns the value at the intersection of a row and column in a given range.
**Formula:**=INDEX(*Array*,*Row_num*,*Column_num*)**Array –**The range of cells**Row_num –**The row to return data from**Column_num –**The column to return the data from*[optional]*

- MATCH returns a position of an item in an array that matches a value.
**Formula:**=MATCH(*Lookup_value*,*Lookup_array*,*Match_type*)**Lookup_value –**The value you want to find in the lookup value array**Lookup_array –**The range containing lookup values**Match_type –**Exact (0), Nearest Less Than (-1), or Nearest Greater Than (1)*[optional]*

Combining the two functions, you are able to effectively beat the limitations and dangers of VLOOKUP. You can build a lookup that allows you to specify the lookup column and return value column completely independently, and also control of the nature of the approximate match, if not exact. The arrays are ranges and you can specific Column_num in place of Row_num, which mean you are not limited to using columns only; this can be used in place of HLOOKUP. It still has the approximate match feature as nearest “less than” by default, and carries the same sort warnings as VLOOKUP. Here’s how the combined function works:

- =INDEX(
*Return_value_range*, MATCH(*Lookup_value*,*Lookup_value_range*,*Match_type*))**Return_value_range –**The range that holds the return values**Lookup_value –**The value you want to find in the lookup value array**Lookup_value_range –**The range containing lookup values**Match_type –**Exact (0), Nearest Greater Than (-1), or Nearest Less Than (1)

Enjoy, and use in good health!

*Example of a INDEX-MATCH formula exposed in an Excel spreadsheet*

DUDE! This saved my sanity! Thanks so much.

um, Vlookup(target,range,match(colHeader,TableHeaders,0),false)

What’s your problem with this?

Hello!

Thank you, I found this interesting, but isn’t your variant limited too? Ideally I would use “like” options not just exact, less, greater.

Any ideas?

Thanks!

Nikolay,

Yes, it is still limited. I believe you can use wildcards by appending asterisks (e.g., “*”&[VALUE]&”*”) on both sides of your lookup value. Give that a try, maybe it will help expand the scope to what you need. Best of luck!

Thanks,

Ben

Can you tell me if I can use vlookup, excel 2003, to search for results within another sheet or folder. This is driving me crazy.

Jim,

You can certainly reference another Sheet or another Excel file (which is what I think you mean by “folder”). Here’s how to format your references for those situations. These examples demonstrate selecting a table of cells, A1 to B4.

If cells are the the current sheet: A1:B4

If cells are in another sheet: SheetName!A1:B4

If cells are in another document, same folder: [filename.xslx]SheetName!A1:B4

If cells are in another document, other folder: ‘C:\path\to\file\[filename.xslx]SheetName’!A1:B4

You can use that format for any of the references in VLOOKUP or INDEX-MATCH, or any formula for that matter.

Hope that helps!

Awesome. Worked exactly as described.

Thank you very much!

Great article. Exactly what I was looking for. Thanks

Hi, Ben. Very informative. Thanks.

Question though. I have a table with a column of Zip codes (cb2:cb71). These are the Zip Codes for a package PICKUP location. DELIVERY location Zip Codes are (cc1:dv2).

The charge for pickup and delivery (zip to zip) is in the table.

I have tried to use vlookup doing this, even index and match. I keep getting #N/A errors. How can I matchup the charge to the pu zip and del zip? Thanks, Rick

Rick, if you want to match on multiple columns like pickup and delivery ZIP codes, one way to do it is to concatenate each individual combined possibility into a single hidden column. Then, use the INDEX MATCH solution on that hidden column to pull your price from the table accordingly. You may have to reformat your sheet a little (since it sounds like you’ve got multiple delivery columns), or perhaps use a new tab in your workbook to do some table transformation behind the scenes. Does that make sense? There are number of other more complicated options as well, such as using a pivot table. Best of luck!

Great solution!

Ben for MVP!

Hi I am not very experienced in excel but I find that vlookup lets me choose the data array from another sheet whereas the index-match gives me N/A. Please advise. I am making a withholding excel sheet that computes everything itself once gross has been added. State taxes are in a table with greater than to less than equal to.

Amanda, there’s no reason why INDEX MATCH shouldn’t work across multiple sheets… There must be something else going on. If you can post some more details, perhaps I can help figure out what’s going on.

I’ve been trying to get this to work with my data for a while now – maybe you can give me a pointer. I am trying to reconcile certain transactions in my ledger to bank account transactions. I’ve made a Vlookup that is pretty lengthy, but works for about 80% of my straight-across matches (sometimes our GL lumps up two or more bank transactions as one journal entry). But the real problem is when I have multiple occurences of the same transaction amount, but multiple times throughout the month. I got a Match Index function to work with one test transaction, but then it doesn’t apply to the rest of my entries.

Here’s an example of the columns I’m working with. All of our GL entries are on the left side, and we have a separate tab that contains the bank transactions to match against.

Trans. Type | Reference | Date | Amount Amount | Date | Ref Number | D/C

AP | Check Paid | 15-Nov | 2500.00

Bank Data

Amount | Date | Ref Number | D/C

2500.00 | 3-Nov| etc..

2500.00 |12 -Nov| etc…

2500.00 | 20-Nov| etc…

2500.00 | 30-Nov| etc…

The tricky thing is that only first two columns of data that the bank provides will match anything we have in our GL. And the bank transactions may be a couple days, or even a couple weeks, away from the GL entry for the corresponding transaction.

Any ideas?

Josh,

Wow, that sounds like a tough situation. Looks like you don’t really have reliable or identifiable fields to do the match. Are there any other fields (reference number, etc.) you can use to match more reliably? If not, my only other through is to use some chronological magic and forego the dates entirely. Meaning, you can make column in your bank data that adds an date-based index (1, 2, 3, 4, etc.) for like amounts in the same month. Then, do the same on the GL data and match using the index so the exact date won’t have to match. That way, the first 2500.00 bank data entry can match with the first 2500.00 GL entry, and so on. Make sense? Not sure if it will work for you, but worth pondering perhaps.

Best of luck!

Hi Ben,

I am also somewhat inexperienced with Excel and need some help with either of these functions, whichever would best work. I have one sheet of customers and another generated by the post office with tracking numbers. I need the tracking numbers inserted corresponding to customer names on my own spreadsheet. I have tried vlookup and seem to always reach an error message. Thanks for your help!

Louisa,

The correct formula might look something like this:

=INDEX(PostOfficeSheet!B:B,MATCH(CustomerSheet!A1,PostOfficeSheet!A:A,0))

PostOfficeSheet is the name of the sheet with the PO data. Column A has the names, and column B has the tracking numbers.

CustomerSheet is the name of the sheet with the Customer data. Column A has the names, and put the above formula in column B to get the tracking number.

Hope that points you more in the right direction!

Awesome…. this was driving me mental…. thank you very much

I believe this is helping me head in the right direction but I still cannot get the desired results.

What I am trying to do:

I am currently working a man-hours sheet of my field workers (50+ workers), their job class’ vary (ie. LBR 1, LB 2,…LBR 6, 45% CARP, 80% CARP, JT CARP, MASON, PLASTER MASON ETC) I am tasked with attempting to sum man hours daily by class ie laborer (LBR 1-LBR 6) Carpenters, Masons etc.

I would LIKE to be able to search partial text of job class like “lbr” so I can find ALL laborers in column A1 and have the correlating hours summed in B1. “Carpenters” A2 and Their total Hours B2 and so on. I’m ok with having a hidden list populate and I then sum and tidy up in a nice neat table later. I just cannot find a way to do ‘if *this cell* says “lbr” at all, display hours from *this cell* if not, don’t display’ I can drag and sum later.

Better yet! Since every “lbr”, for example, shares the row with the hours I’m concerned with, if I could search and sum EVERY lbr’s corresponding hours into 1 cell that would be excellent. By the end of this project I’m going to have 20 working classes and over 50 workers and I’ll need daily sums of each one.

Any direction would be appreciated!

Steven

Steven,

Sounds like you might want to try using the SUMIF function instead of INDEX-MATCH or VLOOKUP. As with both of the latter, you can also use wildcards in SUMIF to do partial matches.

Your formula might look something like this:

=SUMIF(DataSheet!A:A,”*”&SummarySheet!A1&”*”,DataSheet!B1)

DataSheet is the name of the sheet with the raw data. Column A has the labor code and column B has the hours worked.

SummarySheet is the name of the sheet with the summary data. Column A contains the full or partial labor code and column B has the formula above (to get the sum of hours worked).

Hope that gives you an idea of how to tackle this!

Ben,

SUMIF is definitely the way to go! Thank you, the use of wildcards and SUMIF has made this so much more simple. Happy new year!

Hi there! The Match_type parameters (-1) and (1) work the other way around don’t they? Also the sort order of the lookup values does matter if using these parameters to get the approximate match – you said there is no sorting requirement? I’m using Excel 2010..

Phil, good catches! You’re correct on both counts. I will have to update this posting to reflect those changes. Thanks!