Capitalisation of names

P

PayeDoc

Hello All

Where can I find some code that will correctly capitalise names?

I currently have:

Private Sub employee_name_AfterUpdate()
Me!employee_name= StrConv(Me!employee_name, 3)
End Sub

but as everyong knows this doesn't deal properly with the Mc's, Mac's,
hyphenated names, etc.
I have searched the web and this newsgroup but cannot find anything - other
than various opinions that input masks are to be avoided! As this must be
such a universal requirement I am sure the code must be 'out there', but my
VBA isn't up to it (yet!) and I hate trying to reinvent wheels anyway.


Hope someone can help

Many thanks
Leslie Isaacs
 
D

Douglas J. Steele

I suspect there's nothing out there because it's definitely not a trivial
problem!

For example, I know both McDonalds and Mcdonalds. How could software know
which is correct when?
 
P

PayeDoc

Hello Douglas

OK: not so simple then!!

I could get 95% right if I could just capitalise:

the first letter
the first letter after any hyphens
the first letter after any spaces
the first letter after any "Mc" or "Mac" strings

How could I adapt my current code ...
Me!employee_name= StrConv(Me!employee_name, 3)
.... to deal with the 4 cases above?

The user would need to be able to correct the remaining 5% (including the
Mcdonalds etc.) manually - so I guess I would need to move the eventcode
from being on AfterUpdate to on Enter?

Hope you can help!
Thanks again
Leslie Isaacs
 
D

Douglas J. Steele

Something like the following untested air-code:

Function CapitalizeName(NameIn As String) As String
Dim lngPos As Long
Dim strNameOut As String

strNameOut = StrConv(Me!employee_name, 3)

' Capitalize letters after spaces
lngPos = InStr(strNameOut, " ")
Do While lngPos > 0
Mid(strNameOut, lngPos + 1, 1) = _
UCase(Mid(strNameOut, lngPos + 1, 1))
lngPost = InStr(lngPos + 1, strNameOut, " ")
Loop

' Capitalize letters after hyphens
lngPos = InStr(strNameOut, "-")
Do While lngPos > 0
Mid(strNameOut, lngPos + 1, 1) = _
UCase(Mid(strNameOut, lngPos + 1, 1))
lngPost = InStr(lngPos + 1, strNameOut, "-")
Loop

' Capitalize the letter after Mc
If Left(strNameOut, 2) = "Mc" Then
Mid(strNameOut, 3, 1) = UCase(Mid(strNameOut, 3, 1)
Else
lngPos = InStr(strNameOut, " Mc")
If lngPos > 0 Then
Mid(strNameOut, lngPos + 3, 1) = _
UCase(Mid(strNameOut, lngPos + 3, 1))
End Loop
End If

' Capitalize letters after Mac
If Left(strNameOut, 3) = "Mac" Then
Mid(strNameOut, 4, 1) = UCase(Mid(strNameOut, 4, 1)
Else
lngPos = InStr(strNameOut, " Mac")
If lngPos > 0 Then
Mid(strNameOut, lngPos + 4, 1) = _
UCase(Mid(strNameOut, lngPos + 4, 1))
End Loop
End If

CapitalizeName = strNameOut

End Function
 
M

Mike Painter

PayeDoc said:
Hello Douglas

OK: not so simple then!!

I could get 95% right if I could just capitalise:

the first letter
the first letter after any hyphens
the first letter after any spaces
the first letter after any "Mc" or "Mac" strings

How could I adapt my current code ...
Me!employee_name= StrConv(Me!employee_name, 3)
... to deal with the 4 cases above?

The user would need to be able to correct the remaining 5% (including
the Mcdonalds etc.) manually - so I guess I would need to move the
eventcode from being on AfterUpdate to on Enter?

Hope you can help!
Thanks again
Leslie Isaacs
 
M

Mike Painter

PayeDoc said:
Hello Douglas

OK: not so simple then!!

I could get 95% right if I could just capitalise:

the first letter
the first letter after any hyphens
the first letter after any spaces
the first letter after any "Mc" or "Mac" strings

How could I adapt my current code ...
Me!employee_name= StrConv(Me!employee_name, 3)
... to deal with the 4 cases above?
Probably with a lot of if statements.
X = Me!employee_name ' to lazy to type it a lot.
Pos =Instr ( X, "-" )
If Pos then
X = left(X,Pos) & strconv(mid(X,Pos+1),3) "VERY UNTESTED but close.
End If

Pos = Instr(X, "Mc")
If Pos then
X = left(X,Pos) & strconv(mid(X,Pos+2),3) "VERY UNTESTED
End If

Etc.

Why don't you have a first and last name field?

My experience has been that the data entry people will tend to get it right
and that if a mistake is made the named person will correct it if important
to them.
 
L

Linq Adams via AccessMonster.com

Here's a tested hack form a gentleman named Jay Holovacs. It addresses a
large number of the variations in names commonly found, and is modular so
that additional rules for other nationalities can be easily added.

For example it handles names such as:

Henry VIIIK.
O'Hara
Tom McHill
Mary Smith - Jones
McTammany

Call the function with the name passed in any state of capitalization,
returned value is correctly capitalized (original argument is not modified,
making it suitable for use in queries).

Private Sub Text1_AfterUpdate()
Dim retval As String
Me.Text1 = mixed_case(Me.Text1)
End Sub

'************** Code Start *************
'This code was originally written by Jay Holovacs.
'It is not to be altered or distributed,
'except as part of an application.
'You are free to use it in any application,
'provided the copyright notice is left unchanged.
'
'Code Courtesy of
'Jay Holovacs
'
8 1998-2004, Dev Ashish & Arvin Meyer, All rights reserved. Optimized

Public Function mixed_case(str As Variant) As String
'returns modified string, first character of each word us uppercase
'all others lower case
Dim ts As String, ps As Integer, char2 As String
If IsNull(str) Then
mixed_case = ""
Exit Function
End If
str = Trim(str) 'added 11/22/98
If Len(str) = 0 Then
mixed_case = ""
Exit Function
End If
ts = LCase$(str)
ps = 1
ps = first_letter(ts, ps)

special_name ts, 1 'try to fix the beginning
Mid$(ts, 1) = UCase$(Left$(ts, 1))
If ps = 0 Then
mixed_case = ts
Exit Function
End If
While ps <> 0
If is_roman(ts, ps) = 0 Then 'not roman, apply the other rules
special_name ts, ps
Mid$(ts, ps) = UCase$(Mid$(ts, ps, 1)) 'capitalize the first
letter
End If
ps = first_letter(ts, ps)
Wend
mixed_case = ts
End Function
Private Sub special_name(str As String, ps As Integer)
'expects str to be a lower case string, ps to be the
'start of name to check, returns str modified in place
'modifies the internal character (not the initial)

Dim char2 As String
char2 = Mid$(str, ps, 2) 'check for Scots Mc
If (char2 = "mc") And Len(str) > ps + 1 Then '3rd char is CAP
Mid$(str, ps + 2) = UCase$(Mid$(str, ps + 2, 1))
End If

char2 = Mid$(str, ps, 2) 'check for ff
If (char2 = "ff") And Len(str) > ps + 1 Then 'ff form
Mid$(str, ps, 2) = LCase$(Mid$(str, ps, 2))
End If

char2 = Mid$(str, ps + 1, 1) 'check for apostrophe as 2nd char
If (char2 = "'") Then '3rd char is CAP
Mid$(str, ps + 2) = UCase$(Mid$(str, ps + 2, 1))
End If

Dim char3 As String
char3 = Mid$(str, ps, 3) 'check for scots Mac
If (char3 = "mac") And Len(str) > ps + 1 Then 'Mac form
Mid$(str, ps + 3) = UCase$(Mid$(str, ps + 3, 1))
End If

Dim char4 As String
char4 = Mid$(str, ps, 4) 'check for Fitz
If (char4 = "fitz") And Len(str) > ps + 1 Then 'Fitz form

Mid$(str, ps + 4) = UCase$(Mid$(str, ps + 4, 1))
End If

End Sub
Private Function first_letter(str As String, ps As Integer) As Integer
'ps=starting point to search (starts with character AFTER ps)
'returns next first letter, 0 if no more left
'modified 6/18/99 to handle hyphenated names
Dim p2 As Integer, p3 As Integer, s2 As String
s2 = str
p2 = InStr(ps, str, " ") 'points to next blank, 0 if no more
p3 = InStr(ps, str, "-") 'points to next hyphen, 0 if no more
If p3 <> 0 Then
If p2 = 0 Then
p2 = p3
ElseIf p3 < p2 Then
p2 = p3
End If
End If
If p2 = 0 Then
first_letter = 0
Exit Function
End If
'first move to first non blank, non punctuation after blank
While is_alpha(Mid$(str, p2)) = False
p2 = p2 + 1
If p2 > Len(str) Then 'we ran off the end
first_letter = 0
Exit Function
End If
Wend
first_letter = p2
End Function
Public Function is_alpha(ch As String)
'returns true if this is alphabetic character
'false if not
Dim c As Integer
c = Asc(ch)
Select Case c
Case 65 To 90
is_alpha = True
Case 97 To 122
is_alpha = True
Case Else
is_alpha = False

End Select

End Function
Private Function is_roman(str As String, ps As Integer) As Integer
'starts at position ps, until end of word. If it appears to be
'a roman numeral, than the entire word is capped in passed back
'string, else no changes made in string
'returns 1 if changes were made, 0 if no change
Dim mx As Integer, p2 As Integer, flag As Integer, i As Integer
mx = Len(str) 'just so we don't go off the edge
p2 = InStr(ps, str, " ") 'see if there is another space after this word
If p2 = 0 Then
p2 = mx + 1
End If
'scan to see if any inappropriate characters in this word
flag = 0
For i = ps To p2 - 1
If InStr("ivxIVX", Mid$(str, i, 1)) = 0 Then
flag = 1
End If
Next i
If flag Then
is_roman = 0
Exit Function 'this is not roman numeral
End If
Mid$(str, ps) = UCase$(Mid$(str, ps, p2 - ps))
is_roman = 1
End Function
'************** Code End *************

Please honor the author's conditions of use!
 
P

PayeDoc

Hello Douglas

That's great!
With a couple of typos corrected your function did exactly what I needed -
many thanks.

Les
 
P

PayeDoc

Hello

Many thanks for this.
In fact I have used Douglas' simpler function, which was enough for what I
needed.

Thanks again
Les
 
P

PayeDoc

Hello Mike

Many thanks for your reply.
In fact I have used Douglas' function, which was enough for what I needed.

Thanks again
Les
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top