How to Copy Source Formatting When Using VLOOKUP in Excel?
When you use VLOOKUP in Excel, one common frustration is that it retrieves only the value from the source data, but not the formatting (like font color, boldness, or background color). If your dataset uses formatting as a visual cue, this can make your lookup results look inconsistent.
Unfortunately, Excel doesnβt support formatting retrieval natively through formulas. However, you can work around this limitation using VBA (Visual Basic for Applications) or Conditional Formatting. In this guide, weβll walk through reliable methods to ensure your lookup results retain the desired formatting.
Why VLOOKUP Does Not Retain Formatting
By design, VLOOKUP and other Excel formulas only handle values. They donβt carry formatting information because Excel separates a cellβs content (value) from its appearance (formatting).
That means when you run a formula like:
=VLOOKUP(E2, $A$1:$C$8, 3, FALSE)
youβll get the correct value but lose any special styling that was in the source cell.
If formatting consistency is critical, youβll need to use VBA or simulate formatting with Conditional Formatting rules.
Method 1: Using VBA with a Worksheet Event (Recommended)
One common mistake is trying to make a UDF (user-defined function) change formatting directly inside the formula cell. This causes circular reference errors because Excel formulas arenβt allowed to alter formatting.
Instead, you should separate the tasks:
- A formula (or UDF) retrieves the value.
- A worksheet event or macro applies the formatting automatically.
Step 1: Create a Simple Lookup Function (Optional)
In a standard VBA module (Insert > Module
), paste:
Public Function LookupKeepFormat(lookup_value As Variant, table_array As Range, col_index_num As Long) As Variant
LookupKeepFormat = Application.VLookup(lookup_value, table_array, col_index_num, False)
End Function
This works like a normal VLOOKUP, but just returns the value.
Usage in Excel:
=LookupKeepFormat(E2, $A$1:$C$8, 3)
Step 2: Add a Worksheet Event to Copy Formatting
Right-click the sheet tab > View Code, then paste this event procedure:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim watchCol As Range, c As Range
Dim m As Variant, src As Range, outCell As Range
Dim tbl As Range
' Adjust these ranges to fit your sheet
Set watchCol = Me.Range("E2:E100") ' lookup values
Set tbl = Me.Range("$A$1:$C$8") ' source table
Dim hit As Range
Set hit = Intersect(Target, watchCol)
If hit Is Nothing Then Exit Sub
On Error GoTo CleanExit
Application.EnableEvents = False
For Each c In hit.Cells
If Len(c.Value) > 0 Then
m = Application.Match(c.Value, tbl.Columns(1), 0)
If Not IsError(m) Then
Set outCell = c.Offset(0, 1) ' result column (adjust if needed)
Set src = tbl.Columns(1).Cells(m, 1)
outCell.ClearFormats
src.Copy
outCell.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End If
End If
Next c
CleanExit:
Application.EnableEvents = True
End Sub
How it works:
- You enter a lookup value in column E.
- The formula in column F retrieves the value.
- The event automatically copies the formatting from the matched rowβs column A into the result cell.
No circular references, no broken formulas.
Method 2: One-Click Macro for Bulk Operations
If you prefer to update values and formatting in one go (instead of dynamically), you can use a standalone macro. This is great for large datasets.
Paste this into a standard module:
Public Sub VLookupCopyFormat(lookupRange As Range, table_array As Range, col_index_num As Long, outputRange As Range)
Dim i As Long, r As Variant
Dim src As Range, outCell As Range
If lookupRange.Rows.Count <> outputRange.Rows.Count Then
MsgBox "lookupRange and outputRange must have the same number of rows.", vbExclamation
Exit Sub
End If
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
For i = 1 To lookupRange.Rows.Count
r = Application.Match(lookupRange.Cells(i, 1).Value, table_array.Columns(1), 0)
Set outCell = outputRange.Cells(i, 1)
If Not IsError(r) Then
outCell.Value = Application.Index(table_array.Columns(col_index_num), r)
Set src = table_array.Columns(1).Cells(r, 1)
outCell.ClearFormats
src.Copy
outCell.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
Else
outCell.Value = CVErr(xlErrNA)
outCell.ClearFormats
End If
Next i
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Example usage:
Sub RunIt()
VLookupCopyFormat Range("E2:E100"), Range("$A$1:$C$8"), 3, Range("F2:F100")
End Sub
This fills column F with values and formatting in one shot.
Method 3: Using Conditional Formatting
If you donβt want to use VBA at all, you can simulate formatting with Conditional Formatting:
- Select the output range.
- Go to Home > Conditional Formatting > New Rule.
- Choose Use a formula to determine which cells to format.
- Enter a formula such as:
=$E2=$A$1
- Define the formatting you want (bold, background color, etc.).
- Add multiple rules for different conditions.
This wonβt copy exact source formatting, but it gives you a flexible, no-code way to visually align your lookup results.
VBA vs. Conditional Formatting: A Quick Comparison
Feature | VBA | Conditional Formatting |
---|---|---|
Copies Source Formatting | Yes (basic: color, bold, fill) | No (simulation only) |
Dynamic Updates | Yes (event-driven) | Yes (formula-based) |
Programming Needed | Yes | No |
Handles Complex Formatting | No | No |
Final Thoughts
Excel formulas like VLOOKUP are limited to returning values only. If you need to carry over formatting, you have two practical options:
- VBA (event or macro) β best if you want exact formatting copied automatically.
- Conditional Formatting β best if you prefer a simpler, no-code approach.
If your workbooks depend on consistent visual styles, investing a little time in VBA can save you hours of manual formatting in the long run.
FAQs
How do I avoid the circular reference error with a VBA solution?
Donβt change cell formats inside a UDF. Keep the function βpureβ (return value only) and perform formatting with a Worksheet_Change event or a separate macro. This separation prevents circular references and calculation issues.
Whatβs the recommended way to copy formats alongside VLOOKUP results?
Use a two-part approach: a simple return-only function (or native VLOOKUP) for the value, plus a Worksheet_Change event that finds the matched row and copies formats (font color, bold, fill) to the result cell.
Can I copy both values and formats in bulk without events?
Yes. Run a one-click macro that loops through your lookup values, writes the matched result to the output range, and then copies the matched source cellβs formats. This is ideal for large datasets or one-time operations.
Can Conditional Formatting replace VBA for copying source formatting?
Conditional Formatting can simulate the look by applying rules based on lookup matches, but it cannot copy the exact source styles. Itβs a good no-code option when you just need consistent visual cues.
What formatting can be copied and what are the limitations?
VBA can mirror basic styles (fill color, font color, bold/italic). It wonβt copy borders, data bars, icon sets, or other Conditional Formatting rules. If the source tableβs formatting changes, re-run the macro or trigger the event to refresh.

Vaishvi Desai is the founder of Excelsamurai and a passionate Excel enthusiast with years of experience in data analysis and spreadsheet management. With a mission to help others harness the power of Excel, Vaishvi shares her expertise through concise, easy-to-follow tutorials on shortcuts, formulas, Pivot Tables, and VBA.
The VBA code does not work. I get the below error
There are one or more circular references where a formula refers to its own cell either directly or indirectly. This might cause them to calculate incorrectly.
Hey Jeff, thanks for trying it out!
That message usually pops up because Excel formulas arenβt designed to handle formatting changes directly, so it thinks the cell is looping back on itself. The way around it is to split things up: let the formula just grab the value and then use a little event/macro to handle the formatting.
Iβve added the updated steps in the post, so itβll work without that error. Give the new version a shot and it should run smoothly now