TL;DR —
IsNumeric(value)returnsTruewhen VBA thinks it could convert the value to a number — which is a much wider net than the clean integers you probably have in mind. It saysTrueto"1E5"(scientific notation),"&HFF"(a hex literal),"1,000"(a thousands separator)," 42 "(padded with spaces) and even"12-"(a trailing sign). It is also locale-dependent, so"1,5"is a number on a German machine and not on an American one. Use it as a cheap first gate, but the moment you need exactly a clean integer or a digits-only code, pin the shape with the Like operator instead.
Sub IsNumericSurprises()
Debug.Print IsNumeric("123") ' True - as expected
Debug.Print IsNumeric("1E5") ' True - reads as 100000 (scientific)
Debug.Print IsNumeric("&HFF") ' True - reads as 255 (hex literal)
Debug.Print IsNumeric("1,000") ' True - thousands separator
Debug.Print IsNumeric(" 42 ") ' True - leading/trailing spaces ignored
Debug.Print IsNumeric("12-") ' True - trailing sign is allowed
Debug.Print IsNumeric("12.3.4") ' False - two decimal points
Debug.Print IsNumeric("") ' False - empty string
Debug.Print IsNumeric("2026-01-01") ' False - that is a date, use IsDate
End Sub
What you'll learn
- The mental model — IsNumeric tests what VBA could parse, not what you meant
- The three text testers of rising power, and which question each one answers
- Why scientific notation and hex literals sail straight through
- Why spaces, signs, and thousands separators all pass
- Why IsNumeric is locale-dependent, and how that corrupts data across machines
- IsNumeric vs
IsNumbervsIsDate, and the strict check to use instead
The mental model: IsNumeric asks what VBA could parse, not what you meant
IsNumeric is not a validator. It is a preview of VBA's own type coercion: it returns True for any
string that CDbl (or the implicit conversion behind Val-style parsing) would swallow without an
error. That is a deliberately generous rule, because VBA's numeric parser understands scientific
notation, hexadecimal and octal literals, currency and grouping symbols, and surrounding whitespace.
So the right question in your head is never "is this a number?" It is "would VBA convert this to a number if I asked it to?" — and the answer is yes far more often than you want. Every surprise below follows directly from that one framing.
The three testers, of rising power
IsNumeric is the first rung of a ladder. Before you trust any string, you test it — and VBA hands you
three testers, each answering a different question and each lying to you in its own way:
| Tester | The question it answers | Its signature lie |
|---|---|---|
IsNumeric |
Could VBA parse this as a number? | Says yes to "1E5", "&HFF", "12-" |
Like |
Does the whole string fit this shape? | Case depends on a module-wide switch |
| RegExp | Does it match a real pattern, and what is inside? | Returns nothing until you set Global and reach SubMatches |
Reach for the weak one and bad data slips through; reach for the heavy one and you drown in setup. The
skill is knowing which question you are actually asking. IsNumeric answers the loosest question, which
makes it the fastest to reach for and the easiest to get wrong. When "could be a number" is not tight
enough — you need exactly three digits, or a positive amount, or a code with no letters — you have
climbed off the bottom rung and want Like or a real pattern.
Trap 1: scientific notation and hex literals sail straight through
The two that catch everyone: "1E5" and "&HFF".
Debug.Print IsNumeric("1E5") ' True
Debug.Print CDbl("1E5") ' 100000 <- E is an exponent
Debug.Print IsNumeric("&HFF") ' True
Debug.Print CLng("&HFF") ' 255 <- &H is a hex literal
This is not a bug — it is VBA being consistent. But it is a data disaster when the field is a code
rather than a quantity. A product ID like 1E5, an account suffix like 12E3, or a part number that
happens to start &H all pass validation and then get silently turned into a large integer the moment
you convert. The user typed a label; your macro stored a number in the millions and moved on without a
word.
If the column is meant to hold identifiers, IsNumeric is the wrong gate entirely — you do not want
"parseable as a number", you want "these exact characters". That is a job for the
Like operator or a straight string comparison, not IsNumeric.
Trap 2: spaces, signs, and thousands separators all pass
VBA's parser is forgiving about the cosmetics around a number, so all of these return True:
Debug.Print IsNumeric(" 42 ") ' True - surrounding whitespace is trimmed
Debug.Print IsNumeric("+5") ' True - leading sign
Debug.Print IsNumeric("12-") ' True - TRAILING sign (the famous one)
Debug.Print IsNumeric("1,000") ' True - thousands separator
Debug.Print IsNumeric("(5)") ' True - accounting-style negative
The trailing-sign case ("12-") surprises almost everyone, and the accounting parentheses ("(5)")
are a genuine footgun when you import a finance export and half your negatives arrive wrapped in
brackets. Meanwhile the things you might expect to pass do not: an internal space ("1 2"), a fraction
("1/2"), and an empty string all return False. The rule is not "looks like digits" — it is "matches
one of VBA's accepted numeric shapes", and that set is both wider and stranger than intuition.
Trap 3: it is locale-dependent, so it corrupts data across machines
This is the quiet one that survives testing and fails in production. IsNumeric respects the machine's
regional settings for the decimal and grouping separators:
' On a US machine (decimal = ".")
Debug.Print IsNumeric("1,5") ' False - comma is not a decimal point here
Debug.Print IsNumeric("1.5") ' True
' On a German machine (decimal = ",")
Debug.Print IsNumeric("1,5") ' True - comma IS the decimal point
Debug.Print IsNumeric("1.5") ' True - dot read as a grouping separator
The same workbook, the same macro, two different answers depending on who opens it. A validation step
that passes on your desk lets a colleague's "1,5" through as 1.5 — or rejects it outright — and you
will never see it in a test. When the value comes from a file, a web page, or another region, do the
parsing yourself with an explicit assumption (CDbl respects locale; Val always
treats . as the decimal), rather than trusting IsNumeric to mean the same thing everywhere.
IsNumeric vs IsNumber vs IsDate
Three functions people reach for interchangeably, three different jobs:
IsNumeric(x)— a VBA function that asks whether a string could be parsed as a number. This is the one this article is about.Application.WorksheetFunction.IsNumber(cell)— the worksheetISNUMBER, which asks whether a cell's stored value is already of numeric type. It does not parse text;IsNumber("123")on a text-formatted cell isFalseeven thoughIsNumeric("123")isTrue.IsDate(x)— the sibling gate for dates.IsNumeric("2026-01-01")isFalse; useIsDatefor anything that should be a date, and note it is every bit as locale-dependent asIsNumeric.
Use IsNumber when you are asking about a value that is already in a cell; use IsNumeric when you are
sanitising text before you convert it.
The opinion: IsNumeric is a cheap gate, not a validator
IsNumeric earns its place as a fast rejection of obvious garbage — a blank cell, a name, a stray
symbol. Let it throw those out cheaply. But the day your rule is tighter than "could be a number" — a
five-digit ZIP, a positive quantity, an order code with no letters — IsNumeric stops being an
asset and becomes a false sense of safety, because it green-lights scientific notation, hex, padded
strings and locale-specific separators you never meant to accept.
The fix is to say the shape out loud. For "exactly three digits", s Like "###". For "digits only, any
length", Len(s) > 0 And Not (s Like "*[!0-9]*"). For anything with structure — a group to extract, a
pattern that repeats — you have climbed to the top of the ladder and want a
real pattern. And whatever you decide passes, convert it immediately under the same
locale assumption you tested with, so "valid" and "converted" can never disagree.
When validation is the whole job — describe it instead
Half the time the real task is not "is this numeric" but "clean this column: strip the codes that look
like numbers, flag the ones with the wrong number of digits, coerce the rest, and tell me which rows you
touched." By the time you have chained IsNumeric, a Like shape check, a locale-aware conversion and a
log of the exceptions, the plumbing dwarfs the answer.
ExcelMaster lets you state that goal
in plain English — "validate column C as positive whole quantities, list every row that fails and why" —
and it generates Python that reads the data, applies the real rule, backs up your file first, and hands
back the exceptions. You describe the check; it handles the scientific notation, the padding, and the
locale.
Frequently asked questions
What does IsNumeric do in VBA?
IsNumeric(expression) returns a Boolean: True if VBA could convert the expression to a number, and
False otherwise. It is generous — it accepts scientific notation, hexadecimal (&H) and octal (&O)
literals, thousands separators, surrounding whitespace and leading or trailing signs — so it means
"parseable as a number", not "a clean integer".
Why does IsNumeric return True for a value that is not a number?
Because the value is one VBA's parser recognises. "1E5" is scientific notation, "&HFF" is a hex
literal, "1,000" uses a thousands separator, and "12-" has a trailing sign — all valid numeric
shapes to VBA. If you need a stricter definition, test the shape with Like (for example
s Like "###" for exactly three digits) instead of IsNumeric.
How do I check that a string is only digits in VBA?
Use a Like pattern rather than IsNumeric. Len(s) > 0 And Not (s Like "*[!0-9]*") is True only
when s is non-empty and contains no non-digit character — a genuine digits-only test that, unlike
IsNumeric, rejects "1E5", "1,000" and "12-".
What is the difference between IsNumeric and IsNumber in VBA?
IsNumeric is a VBA function that tests whether a string could be parsed as a number.
WorksheetFunction.IsNumber (the worksheet ISNUMBER) tests whether a cell's value is already stored
as a numeric type. A text cell containing 123 gives IsNumeric = True but IsNumber = False.
Is IsNumeric affected by regional settings?
Yes. IsNumeric uses the machine's decimal and grouping separators, so "1,5" is numeric on a machine
where the comma is the decimal point and not on one where the dot is. For portable results, convert with
an explicit rule (Val always uses . as the decimal; CDbl respects the current locale) instead of
relying on IsNumeric to behave identically everywhere.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-09-04.
Related guides: VBA Like · VBA Regex · VBA CStr · VBA InStr · VBA Split
