🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA Like Operator in Excel — Wildcard Matching and the Whole-String Trap

|

VBA Like Operator in Excel — Wildcard Matching and the Whole-String Trap

TL;DRtext Like pattern returns a Boolean: does the entire string match the wildcard pattern? The wildcards are * (any run of characters), ? (exactly one character), # (exactly one digit), [abc] (one character from a set) and [!abc] (one character not in the set). Two things bite: Like matches the whole string, so testing for a substring needs "*abc*", not "abc"; and its case sensitivity is set module-wide by Option Compare, with no per-call flag the way InStr has one.

Sub LikeBasics()
    Debug.Print "Excel"   Like "Ex*"        ' True  - starts with "Ex"
    Debug.Print "Excel"   Like "*x*"        ' True  - contains an "x"
    Debug.Print "Excel"   Like "?????"      ' True  - exactly five characters
    Debug.Print "A-1234"  Like "[A-Z]-####" ' True  - letter, dash, four digits
    Debug.Print "cat"     Like "[!0-9]*"    ' True  - does not start with a digit

    Debug.Print "Excel"   Like "x"          ' False - Like matches the WHOLE string
    Debug.Print "Excel"   Like "excel"      ' False - case-sensitive by default
End Sub

What you'll learn

  • The mental model — Like is a shape test, not a search
  • Each of the five wildcards and exactly what it matches
  • Why Like checks the whole string, so a substring test needs surrounding *
  • Why case sensitivity is a module-wide Option Compare switch, not a per-call flag
  • How to match a literal *, ?, # or [ with the bracket escape
  • Like vs InStr vs the worksheet wildcards, and which to reach for

Like is not looking inside your string for something. It lays the pattern over the string end to end and asks a single yes/no question: does this whole string have this shape? That is a different job from InStr, which searches for a substring and reports where it is, and from a regular expression, which can find, count, and extract pieces. Like returns nothing but True or False.

That framing tells you when it fits: you have a fixed shape and you want a verdict. Is this a valid SKU ("[A-Z][A-Z]-####")? Does this filename end in .xlsx ("*.xlsx")? Does this code contain only digits (Not (s Like "*[!0-9]*"))? Every one of those is a shape question, and Like answers it in one readable line — no object to create, no loop, no position arithmetic.

The wildcards, and what each one matches

Five special tokens, and everything else in the pattern is a literal that must appear exactly:

Wildcard Matches Example that returns True
* zero or more of any character "report_2026.xlsx" Like "*.xlsx"
? exactly one character "b1g" Like "b?g"
# exactly one digit (0-9) "A7" Like "A#"
[list] one character in the list or range "m" Like "[a-m]"
[!list] one character not in the list "x" Like "[!aeiou]"

Ranges inside brackets go low to high ([A-Z], [0-9]), and you can combine sets ([A-Za-z0-9]). The # wildcard is a VBA convenience with no equivalent in worksheet wildcards, and [!...] negation is the tool behind most real validation — "*[!0-9]*" means "contains at least one non-digit somewhere", which you negate to assert "digits only".

Trap 1: Like checks the whole string, not a substring

This is the number-one "Like is not matching" question, and it comes from expecting search behaviour:

Debug.Print "Invoice 2026" Like "2026"     ' False - the string is not JUST "2026"
Debug.Print "Invoice 2026" Like "*2026*"   ' True  - contains "2026" anywhere
Debug.Print "Invoice 2026" Like "Invoice*" ' True  - starts with "Invoice"

The pattern has to describe the string from first character to last. If you only care that a fragment appears somewhere, wrap it in * on both sides. If you genuinely just want "does this contain that literal text", InStr is the more direct tool — InStr(s, "2026") > 0 — and it is faster because there is no pattern to interpret. Reach for Like when the shape matters (anchored at the start, a digit here, a letter there), not merely the presence of a substring.

Trap 2: case depends on Option Compare, with no per-call override

By default a module uses Option Compare Binary, so Like is case-sensitive:

Debug.Print "Excel" Like "excel"   ' False under Option Compare Binary (the default)

Put Option Compare Text at the very top of the module (above every procedure) and every string comparison in that module — =, Like, InStr without an explicit argument — becomes case-insensitive:

Option Compare Text          ' module-wide, at the top of the module

Sub CaseInsensitive()
    Debug.Print "Excel" Like "excel"   ' True now
End Sub

Here is the sharp difference from its cousins: Like has no per-call case flag. InStr and Filter both take vbTextCompare as an argument, so you can ignore case for one call and stay case-sensitive everywhere else. Like cannot — its case behaviour is a property of the whole module. If you need case-insensitive matching in just one spot without flipping the module, fold the case yourself with UCase: UCase(s) Like "EXCEL". That keeps the effect local and obvious, instead of hiding it in an Option line a hundred lines away.

Trap 3: matching a literal asterisk, question mark, or bracket

Sooner or later you need to match a real * or ? — a filename with a wildcard in it, a search box that literally contains #. Escape a special character by putting it inside brackets:

Debug.Print "3*4"  Like "*[*]*"   ' True  - contains a literal asterisk
Debug.Print "OK?"  Like "*[?]"    ' True  - ends with a literal question mark
Debug.Print "C#"   Like "*[#]"    ' True  - literal hash (not "a digit")
Debug.Print "a[1]" Like "*[[]*"   ' True  - literal opening bracket

Note this is not the worksheet convention. Range.Find, Application.Match and COUNTIF escape a wildcard with a leading tilde (~*, ~?), and they do not understand # or [!list] at all. Two different wildcard dialects live in the same product, and mixing them up — using ~* in a Like pattern, or [*] in a Find — is a subtle, silent source of matches that never fire.

Like vs InStr vs the worksheet wildcards

The one-line decision, so you stop reaching for the wrong tool:

  • InStr — you want to know whether and where a literal substring appears. Fastest for "contains this exact text".
  • Like — you want a yes/no on a shape: anchored, positional, digit-vs-letter, a bounded set. One Boolean, whole string.
  • Range.Find / worksheet wildcards — you are matching against cells on a sheet, and the dialect is *, ?, and ~ to escape. Different tool, different wildcards.
  • RegExp — the shape has repetition counts, alternation (this|that), or a group you need to pull out. That is past what Like can express.

When the pattern outgrows Like — describe the job instead

Like is a joy right up to the point where the shape stops being fixed. The moment the rule becomes "three-to-five letters, then a dash, then a variable number of digits, and pull the digits out", you are writing loops around Like, or bolting on Mid and InStr, and the intent disappears into plumbing. That is the signal to either climb to a real pattern — or skip the code entirely. ExcelMaster lets you state the rule in plain English — "keep the rows whose code is three letters then four digits, and put the digits in column D" — and it generates Python that applies the match, backs up your file first, and writes the result. You describe the shape; it handles the wildcards, the case, and the edges.

Frequently asked questions

What does the Like operator do in VBA?

Like compares a string to a pattern and returns True if the whole string matches. The pattern can contain wildcards: * (any run of characters), ? (one character), # (one digit), [list] (one character from a set) and [!list] (one character not in the set). It returns a Boolean, so it is used inside If and Do While conditions.

Why is my VBA Like comparison not matching?

Two usual causes. First, Like matches the entire string, so "Invoice 2026" Like "2026" is False — wrap the fragment in asterisks: "*2026*". Second, it is case-sensitive under the default Option Compare Binary, so "Excel" Like "excel" is False until you add Option Compare Text to the top of the module or fold the case with UCase.

How do I make VBA Like case-insensitive?

Put Option Compare Text at the top of the module — it makes every string comparison in that module case-insensitive, Like included. Like has no per-call case argument the way InStr and Filter do, so for a one-off case-insensitive match without changing the module, compare folded strings instead: UCase(value) Like "PATTERN".

How do I match a literal asterisk or question mark with Like?

Wrap the special character in brackets: [*] matches a literal asterisk, [?] a literal question mark, [#] a literal hash and [[] a literal opening bracket. For example "3*4" Like "*[*]*" is True. This bracket escape is specific to Like; worksheet tools such as Range.Find use a leading tilde (~*) instead.

When should I use Like instead of a regular expression in VBA?

Use Like when the shape is fixed and you only need a yes/no: a file extension, a fixed-length code, a digits-only check. Reach for a RegExp when the pattern has variable repetition (\d{2,4}), alternation (cat|dog), or a capture group you need to extract. Like cannot count repetitions or return the matched pieces; a regular expression can.

Tested in

Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-09-04.

Related guides: VBA IsNumeric · VBA Regex · VBA InStr · VBA Find · VBA UCase and LCase