TL;DR —
text Like patternreturns 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:Likematches the whole string, so testing for a substring needs"*abc*", not"abc"; and its case sensitivity is set module-wide byOption 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 Compareswitch, not a per-call flag - How to match a literal
*,?,#or[with the bracket escape - Like vs
InStrvs the worksheet wildcards, and which to reach for
The mental model: Like is a shape test, not a search
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 whatLikecan 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
