Proper Name Case Excel VBA Function
Apply proper capitalization to surnames/family names/last names in Excel.
This function generated the following names:
- Ronald McDonald
- Roland MacDonald
- Jerald D'Angelo
- Gail van Stolk
- Earl Mackie
- Michael Murphy
- John St. John
- Larry St John
- Gordon Saint John
- Arthur Stevens
- Dennis McLaughlin
- Gary McRae
- Timothy MacRae
- John Grove White
- Richard Graham-Nichols
- Frank McDonald-White
- Robert O'Neil
- William van der Meir
- Marian di Castri
- Anwar al-Sadat
- Yves St-Laurent
- Charlie McNeill O'Maley
- D'Artagne St.John-O'Maley
Installation
In Excel, press Alt + F11 to enter the code editor. Select Insert > Module and paste the code below into your new module file.
Back in your worksheet you can now run the NameCase method using =NameCase(A1), etc.
My version uses regular expressions which, apparently, are new to VBA. You might need a recent version of Excel to make this work.
Important!
This script does the job but can take some time processing a lot of data. I strongly recommend you use it on about 1,000 records at a time.
Contact
Written by Alex Dunae (dunae.ca, e-mail 'code' at the same domain), 2008. Excel/VBA is definitely not my strong suit—any improvements (especially performance-related) are welcome. Updates will be announced at http://twitter.com/TheCHANGELOG and on the Atom feed.
Incidentally, Webessence’s code highlighter is fantastic.
Code
For copy-and-paste action, grab the source as a text file. You can also download the Excel file with test cases. You will have to enable macros on startup.
Option Explicit
Function NameCase(Raw As String) As String
Application.ScreenUpdating = False
Dim RE As Object
Dim NameParts, NamePart
Dim Converted As String
' Setup the regexp object
Set RE = CreateObject("vbscript.regexp")
RE.IgnoreCase = True
RE.Global = True
' Break names into parts and process them individually
Set NameParts = RE.Execute(Raw)
RE.Pattern = "(^|\s|\-)+(.[^\s^-]+)"
Converted = ""
' Iterate through name parts
For Each NamePart In NameParts
' Check for surname "prefixes"
RE.IgnoreCase = True
RE.Pattern = "(^|\s)+(van|von|der|de|la|di|al)($)"
If RE.Test(NamePart.SubMatches(1)) Then
' Don't process surname prefixes, just make them lower case
Converted = Converted & NamePart.SubMatches(0) & LCase$(NamePart.SubMatches(1))
Else
' Run the name part through case conversion
Converted = Converted & NamePart.SubMatches(0) & NameCase_Individual(NamePart.SubMatches(1), RE)
End If
Next
Application.ScreenUpdating = True
NameCase = Converted
End Function
' Convert a name-part to proper case
' RE is a regexp object, passed in so we're not always creating new objects
Function NameCase_Individual(Raw As String, RE As Object) As String
Dim Matches, Match
Dim Converted As String, RemainingName As String
' Setup the regexp object
RE.IgnoreCase = True
RE.Global = False
' Default case capitalizes the first letter and makes the rest lowercase
Converted = UCase$(Left(Raw, 1)) & LCase$(Mid$(Raw, 2, Len(Raw) - 1))
' Pattern matching for names like D'Angelo, McDonald, St. John, St John, 0'Neil
RE.Pattern = "(^|\s)+(Mc|[DO]\'|St\.|St[\.]? )([a-z]+)"
Set Matches = RE.Execute(Converted)
For Each Match In Matches
RemainingName = Match.SubMatches(2)
RemainingName = UCase$(Left(RemainingName, 1)) & Mid$(RemainingName, 2, Len(RemainingName) - 1)
Converted = Match.SubMatches(0) & Match.SubMatches(1) & RemainingName
Next
' Pattern matching for names like MacDonald, MacRae
RE.Pattern = "(^|\s*)(Mac)([dr])([a-z -]+)"
Set Matches = RE.Execute(Converted)
For Each Match In Matches
Converted = Match.SubMatches(1) & UCase(Match.SubMatches(2)) & Match.SubMatches(3)
Next
NameCase_Individual = Converted
End Function