Friday, November 21, 2008
Propercase.Net

p style="text-align: left">Long ago we did a Redmond VisualBasic Developers Association presentation on how to create and use VB collections. Many from the audience liked it more for what it did than how it did it.

 

I was surpised to see the hitcount on that old code's page still being relatively high so I figured I'd bring it up to the 21st century. For this VB.Net port, the old demonstration classes and collections have been removed and just the functionality remains.

If you like StrConv but need it to really do the job, stick this class in your project and let it do the work for you.

The class is really simple to use and you have control over whether you fix acronyms, embedded apostrophes or both. Notice that the acronym fixer also knows how to deal with periods that are not in acronyms (as in "Jr."), the apostrophe routine accounts for possessives while fixing both the single quote and the "`" (that thing under the "~", next to the 1 key. For some reason, direct mail companies like to use that character interchangeably with the apostrophe and it's really annoying).

Are there better ways? Sure, but this way works with the extra touches and is already written for you <g>

Public Class ApostonymFixer

    Private m_arPhrase() As String

    Public Enum rcsTypeOfCheck
        rcsCheckAcronym = 0
        rcsCheckApostrophe = 1
        rcsCheckApostroNym = 2
    End Enum

    Public Function FixText(ByVal textToCheck As String, _
        Optional ByVal typeOfCheck As rcsTypeOfCheck = rcsTypeOfCheck.rcsCheckApostroNym) _
        As String

        PrepareText(textToCheck)

        Select Case typeOfCheck
            Case rcsTypeOfCheck.rcsCheckAcronym
                'uppercase letters before and
                'after the dot
                FixAcronym()
            Case rcsTypeOfCheck.rcsCheckApostrophe
                FixApostrophe()

            Case rcsTypeOfCheck.rcsCheckApostroNym
                FixAcronym()
                FixApostrophe()
        End Select

        Return String.Join(" ", m_arPhrase)


    End Function

    Private Sub FixAcronym()
        Dim i As Integer
        Dim TempWord As String

        'just for fun use ForEach in this one and an int indexer in the other one

        For Each s As String In m_arPhrase
            'pad for lookaheads
            TempWord = s & " "
            i = 1
            Do Until i = Len(TempWord)
                If i > 1 Then
                    If Mid(TempWord, i, 1) = "." Then
                        Mid(TempWord, i - 1, 3) = Mid(TempWord, i - 1, 3).ToUpper
                    End If
                    'this takes care of things
                    'like Jr.
                    If i > 2 Then
                        If Mid(TempWord, i, 1) = "." And Mid(TempWord, i - 2, 1) <> "." Then
                            Mid(TempWord, i - 1, 1) = Mid(TempWord, i - 1, 1).ToLower
                        End If
                    End If
                End If
                i += 1
            Loop
            'kill the pad
            'and update the array element
            s = TempWord.Trim
        Next

    End Sub


    Private Sub FixApostrophe()

        Dim tempWord As String
        Dim foundAt As Integer

        'just for fun use an int indexer in this and a ForEach in the other one

        For iCounter As Integer = 0 To m_arPhrase.Length - 1
            tempWord = m_arPhrase(iCounter).ToString & " "
            foundAt = tempWord.IndexOf("'"c)

            If foundAt = 1 AndAlso Len(tempWord) > 2 Then
                tempWord = Mid(tempWord, 1, 1).ToUpper & "'" & _
                           Mid(tempWord, foundAt + 2, 1).ToUpper & _
                           Mid(tempWord, foundAt + 3, Len(tempWord) - foundAt).ToLower

            End If
            m_arPhrase(iCounter) = tempWord.Trim

            'this also works but does more iteration
            'than is typically required
            'the foundAt variable isn't required for this
            'For i As Integer = 1 To Len(TempWord)
            '    If Mid(tempWord, i, 1) = "'" Then
            '        If Mid(tempWord, i + 2, 1) <> " " AndAlso i = 2 Then
            '            Mid(tempWord, i + 1, 1) = Mid(tempWord, i + 1, 1).ToUpper
            '        Else
            '            Mid(tempWord, i + 1, 1) = Mid(tempWord, i + 1, 1).ToLower
            '        End If
            '    End If
            'Next

        Next


    End Sub


    Private Sub PrepareText(ByVal phrase As String)

        'get rid of double spaces
        Do While phrase.IndexOf("  ") > 0
            phrase = phrase.Trim.Replace("  ", " ")
        Loop

        'get rid of the abnormal slash
        'CHECK WITH YOUR PM to make sure that you're not the one company 
        'in the world that uses this character
        phrase = phrase.Trim.Replace("`", "'")

        'init to proper
        phrase = StrConv(phrase, VbStrConv.ProperCase)
        'the traditional keyword is also fine:
        'phrase = StrConv(phrase, vbProperCase)

        'split to the array
        m_arPhrase = phrase.Split(" "c)
    End Sub

End Class

Why the Mids instead of .Net's SubString? If you use VB.Net or call into the core Framework VisualBasic.Dll from any other language then then using the Mid, Left and Rights means not having the allocation overhead of .Net immutable strings; That's a trick that comes in handy in code like we have above. MS documents the use of the optimized traditional keywords in some cases at up to 85% better performance over the Framework's SubString and thus for some situations they are recommended over the Framework's SubString.

Hope it helps.

 

Robert Smith
Kirkland WA

originally added to smithvoice Sept 15 1999, .Net code page added August 2005


Print  

pagecomment
  Add Comment



Submit Comment
  View Ratings
50.00%0
40.00%0
30.00%0
20.00%0
10.00%0

Number of Comments 0 , Average of Ratings
  View Comments
No comment.


Privacy Statement  |  Terms Of Use
Copyright 2008 by Robert C. Smith