How to Compare Two Lists in VBA (Excel Macro)

Most VBA "compare two columns" macros people copy-paste online use a nested loop, which works but slows to a crawl on large ranges. Here's the fast approach using Scripting.Dictionary, plus two simpler alternatives for smaller lists, in order of how often you'll actually reach for each.

Quick answer

For large ranges, load list B into a Scripting.Dictionary as keys, then loop through list A checking dict.Exists(cellValue) - roughly O(n plus m), similar to a hash set. For small ranges (a few hundred rows or fewer), WorksheetFunction.CountIf(rangeB, cellValue) is simpler to write but rescans rangeB for every cell in rangeA. Add Option Compare Text at the top of the module for case-insensitive string comparison throughout.

Need the same thing in another language?

See the full reference for Python, JavaScript, SQL, and more - or the no-macro Excel guide.

See every language →

Scripting.Dictionary: the fast approach for large ranges

Sub CompareTwoLists()
    Dim dict As Object
    Dim arrA As Variant, arrB As Variant
    Dim i As Long, outputRow As Long
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Sheet1")

    ' Late binding - no References needed
    Set dict = CreateObject("Scripting.Dictionary")

    ' Read both ranges into memory in one shot - avoids slow cell-by-cell access
    arrA = ws.Range("A2:A" & ws.Cells(ws.Rows.Count, "A").End(xlUp).Row).Value
    arrB = ws.Range("B2:B" & ws.Cells(ws.Rows.Count, "B").End(xlUp).Row).Value

    ' Load list B into the dictionary as keys
    For i = LBound(arrB, 1) To UBound(arrB, 1)
        If Not dict.Exists(arrB(i, 1)) Then dict.Add arrB(i, 1), True
    Next i

    ' Walk list A, write out anything not found in B
    outputRow = 1
    For i = LBound(arrA, 1) To UBound(arrA, 1)
        If Not dict.Exists(arrA(i, 1)) Then
            ws.Cells(outputRow, "D") = arrA(i, 1)
            outputRow = outputRow + 1
        End If
    Next i
End Sub

Reading both ranges into Variant arrays first, then looping in memory, avoids the single biggest slowdown in VBA macros - crossing from VBA into Excel's calculation engine on every cell access. The Dictionary lookup itself is O(1) per check, so the whole macro runs in roughly O(n + m) instead of O(n * m) for a nested-loop version.

Early binding for faster Dictionary calls

' Tools > References > Microsoft Scripting Runtime
Dim dict As Scripting.Dictionary
Set dict = New Scripting.Dictionary

Late binding (CreateObject) needs no reference and runs anywhere, but early binding gives you IntelliSense and is marginally faster since VBA doesn't have to resolve method calls at runtime. For a macro you're distributing to other machines, late binding is safer since you can't guarantee the recipient has the same reference checked.

CountIf: simpler, fine for smaller lists

Sub CompareWithCountIf()
    Dim cell As Range
    Dim rangeB As Range
    Set rangeB = ThisWorkbook.Sheets("Sheet1").Range("B2:B500")

    For Each cell In ThisWorkbook.Sheets("Sheet1").Range("A2:A500")
        If WorksheetFunction.CountIf(rangeB, cell.Value) = 0 Then
            Debug.Print cell.Value & " is only in list A"
        End If
    Next cell
End Sub

No Dictionary, no array reading - just a direct worksheet function call per cell. It's easy to read and fine for a few hundred rows, but CountIf re-scans the entire rangeB for every single cell checked, so it becomes noticeably slow well before the Dictionary version would.

Case sensitivity and the Option Compare directive

Option Compare Text   ' place at the very top of the module, above any Sub

VBA string comparisons default to Option Compare Binary (case-sensitive) unless a module says otherwise. Option Compare Text switches string comparisons - including = and Dictionary key lookups on string keys - to case-insensitive for the whole module. It must be the very first line of the module, before any procedure declarations.

Or skip the macro entirely. Paste both columns instead.

Open Compare 2 Lists →

Frequently Asked Questions

What is the fastest way to compare two lists of values in VBA?
Load one list into a Scripting.Dictionary as keys, then loop through the second list checking .Exists() against it. This is roughly O(n + m), the same idea as a hash set in Python or C#, and dramatically faster than comparing cell-by-cell with nested loops once either list has more than a few hundred rows.
Do I need a reference for Scripting.Dictionary?
Not necessarily. With early binding, add a reference to "Microsoft Scripting Runtime" (Tools > References in the VBA editor) and declare Dim dict As Scripting.Dictionary. With late binding, skip the reference entirely and use Dim dict As Object then Set dict = CreateObject("Scripting.Dictionary") - slightly slower but portable to machines without the reference set.
Is VBA CountIf a good alternative to Dictionary?
WorksheetFunction.CountIf(rangeB, cellValue) works for smaller lists and avoids Dictionary entirely, but it re-scans the whole of rangeB for every cell in rangeA, making it O(n * m). Fine for a few hundred rows; noticeably slow past a few thousand.
How do I make the comparison case-insensitive in VBA?
Add Option Compare Text at the very top of the module (above any procedures) to make all string comparisons in that module case-insensitive by default, including = and Dictionary key lookups when keys are strings. Without it, VBA string comparison is case-sensitive by default (Option Compare Binary).
Why is my macro so slow when comparing large ranges?
Reading and writing cells one at a time inside a loop is the usual bottleneck - each cell access crosses from VBA into Excel's calculation engine. Read the whole range into a Variant array in one line (arr = Range("A1:A10000").Value) before looping over it in memory, then write results back in one batch at the end.
Can I skip the macro entirely and just compare two columns?
Yes - paste both columns into the Compare 2 Lists tool and it computes A-only, B-only, intersection, and union instantly with no VBA, no References dialog, and no macro security warnings. See our guide to comparing Excel columns for more approaches, including formula-only ones.
How do I get items in exactly one list (symmetric difference) in VBA?
Run the Dictionary approach twice - once with list A as keys checking against list B, once with list B as keys checking against list A - and combine both result sets. There is no built-in symmetric-difference operator in VBA the way there is in Python or C#.

Share this tool

Featured on ToolDirs
© 2026 ListDiff

Free online list and text processing tools.