TL;DR —
UCaseandLCaseflip text to all-caps or all-lowercase. The mistake is thinking they're for cleaning data. They're for two jobs only: comparing (VBA's=is case-sensitive, so"Yes" = "yes"isFalse— normalize both sides withUCasebefore you compare) and displaying. They are lossy and irreversible, so never overwrite stored data with them. And for Title Case there's no built-inPCase— you useStrConv(s, vbProperCase), which works for plain names but manglesMcDonald,O'Brien, andiPhone.
Changing case feels like the simplest thing in VBA, and UCase/LCase
themselves are simple. The bugs come from why people reach for them. Used as a
comparison tool, they're indispensable. Used as a storage tool, they quietly
destroy information.
What you'll learn
- Why
"Yes" = "yes"isFalsein VBA — and the right way to compare ignoring case - Three ways to do a case-insensitive match (and which to pick)
- Why you should never store
UCaseoutput over your original data StrConvfor Title Case — and the proper-noun trap that comes with it
The mental model: case is for comparing and displaying, not for storing
Think of UCase/LCase as a pair of lenses you look through, not edits you
make to the page. When you want to know whether two strings match regardless of
case, you look at both through the same lens (UCase them) and compare what you
see — the page underneath is untouched. The moment you treat the lens as an
edit — writing UCase(name) back over name — you've thrown away the original
capitalization forever.
Sub TheLensIdea()
Dim stored As String
stored = "McDonald" ' the real data — keep it
' Compare through a lens, don't change the data
If UCase(stored) = UCase("mcdonald") Then
Debug.Print "match" ' this prints
End If
Debug.Print stored ' still "McDonald" — untouched
End Sub
The rule that catches the #1 case bug: VBA's = is case-sensitive
This is the failure mode behind a huge share of "my If never runs" questions. By default VBA compares strings byte for byte, so capitalization matters:
Sub CaseSensitiveByDefault()
Dim answer As String
answer = "YES" ' what the user actually typed
If answer = "yes" Then ' FALSE — "YES" <> "yes"
Debug.Print "confirmed" ' never runs
End If
' Fix: normalize both sides through the same lens
If UCase(answer) = "YES" Then ' TRUE
Debug.Print "confirmed" ' runs
End If
End Sub
You have three ways to make a comparison case-insensitive, and the choice is a real judgment call:
UCase/LCaseboth sides —UCase(a) = UCase(b). Explicit, local, obvious to the next reader. Best default for a one-off compare.StrComp(a, b, vbTextCompare)— returns 0 when equal ignoring case. Cleanest when you specifically want a comparison and nothing else.Option Compare Textat the top of the module — makes every=,Like, andInStrin that module case-insensitive. Powerful but invisible: someone reading one line can't tell the comparison rules changed. Use it sparingly and only when the whole module wants that behavior.
My rule: prefer explicit UCase for a single compare; use Option Compare Text
only when an entire module is genuinely case-insensitive, and comment it loudly.
Dictionary keys are case-sensitive too
The same trap bites Scripting.Dictionary. By default
d("USA") and d("usa") are two different keys — you'll get duplicate
entries you didn't expect. Either set d.CompareMode = vbTextCompare right after
creating it, or UCase every key before you store or look it up. Pick one and be
consistent.
Title Case: there is no PCase, so you use StrConv
VBA gives you UCase and LCase but no built-in proper-case function. The
tool is StrConv with the vbProperCase flag:
Debug.Print StrConv("john smith", vbProperCase) ' -> "John Smith"
That works beautifully for ordinary lowercase input. But StrConv only knows one
rule — capitalize the first letter of each word, lowercase the rest — and that
rule is wrong for a lot of real names:
Debug.Print StrConv("McDonald", vbProperCase) ' -> "Mcdonald" (wrong)
Debug.Print StrConv("O'BRIEN", vbProperCase) ' -> "O'brien" (wrong)
Debug.Print StrConv("iPhone", vbProperCase) ' -> "Iphone" (wrong)
Debug.Print StrConv("ACME III", vbProperCase) ' -> "Acme Iii" (wrong)
The judgment: StrConv(..., vbProperCase) is a "good enough" cleaner for free-
text names and addresses where the input is all-caps or all-lowercase. It is
not a brand/proper-noun formatter. If correctness matters for specific names,
keep an exceptions list and fix them after StrConv, or don't auto-title-case at
all.
StrConv does far more than case, which is why it's the right home for this — it
also converts between half-width and full-width (vbWide/vbNarrow) and between
Hiragana and Katakana (vbHiragana/vbKatakana) for East Asian text, plus byte/
Unicode conversions. Worth knowing the flag list exists when you hit those needs.
How ExcelMaster helps
Most case-handling VBA is part of a cleanup pass: standardize a column so matches and lookups stop missing. ExcelMaster does that from a description — "match these two customer lists ignoring case and spacing" — and normalizes for the comparison without destroying the display values in your sheet. You describe the intent (case-insensitive match, Title Case for display) and it keeps the original data intact.
You'll still write UCase/LCase inline in macros. But for "clean and match
these columns" work, stating the rule beats hand-normalizing every key.
Frequently asked questions
How do I convert text to uppercase or lowercase in VBA?
Use UCase(text) for all-caps and LCase(text) for all-lowercase. They return
a new string and don't modify the original, so assign the result somewhere if you
want to keep it.
How do I do a case-insensitive comparison in VBA?
Normalize both sides with the same function — UCase(a) = UCase(b) — or use
StrComp(a, b, vbTextCompare) which returns 0 when the strings are equal
ignoring case. For a whole module, Option Compare Text makes every comparison
case-insensitive.
How do I capitalize the first letter of each word in VBA?
Use StrConv(text, vbProperCase). Be aware it lowercases everything else, so it
turns McDonald into Mcdonald and iPhone into Iphone. For names with
internal capitals, correct them with an exceptions list afterward.
Why does StrConv mess up names like McDonald?
vbProperCase follows one rigid rule: uppercase the first letter of each word,
lowercase the rest. It has no knowledge of proper nouns, so any name with an
internal capital (McDonald, MacLeod, iPhone) or apostrophe (O'Brien)
comes out wrong. Treat it as a best-effort cleaner, not an authority on names.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-06-14.
Related guides: VBA Concatenate · VBA Str · VBA Replace · VBA Dictionary · VBA For Loop
