Merged Salutations

adam087

Well-known Member
Joined
Jun 7, 2010
Messages
1,356
Hi All

I put together this UDF for some of my coworkers to turn a list of residents/guests/passengers in to useful salutations in order that communication might be better personalised. I'm posting it here because a) it saves us LOADS of time and therefore might help someone else; and b) the coding is my usual amateur stuff and would welcome any feedback on its improvement.

Here's what it does...

Excel 2010
ABCDEF
1Room NoTitleSurnameRoom NoSalutation
21MrJames1Mr & Mrs James
31MrsJames2Lord Smith & Lady Jones
42LordSmith3Mr Horton
52LadyJones4Mrs Sutcliffe
63MrHorton5Mr & Mrs & Miss Brady
74MrsSutcliffe6Dr & Mrs Way
85MrBrady
95MrsBrady
105MissBrady
116DrWay
126MrsWay

<tbody>
</tbody>


Worksheet Formulas
CellFormula
F2=salulookup(E2, $A$1:$C$16, 2, 3)

<tbody>
</tbody>

<tbody>
</tbody>

-----------------------------------------------

And here's the code

Code:
Option Explicit

Public Function SALULOOKUP(sGroupOn As String, rList As Range, iTitle As Integer, iSurname As Integer, Optional andSymbol As String = "&")' Works similarly to a vLookup
' Returns the names grouped on the initial string - e.g. Cabin 1 - Mr & Mrs Smith
' Could be cabin/room number or booking reference.
' As with vLookup, the groupOn string must be in the first column of the range 'list'
'
' Can handle up to 4 persons per group
'


' I'm not sure how to handle it if we get the entire
' Column passed in, so I'll just not allow it (although with useful error)
If rList.Rows.Count > (2 ^ 18) Then
    SALULOOKUP = "#VALUE - Choose Smaller Range"

Else
    
    Dim persons(3) As person
    
    ' rangeToCheck will be defined as the first column of the entire region being searched
    Dim rangeToCheck As Range
    With rList
        Set rangeToCheck = rList.Worksheet.Range(.Cells(.Row, 1), .Cells(.Rows.Count, 1))
    End With

    ' We're only interested where the first cell matches the groupOn string
    ' Collect all the names in to the array; nameCount is always the length of the array
    Dim r As Range, personCount As Integer
    personCount = 0
    For Each r In rangeToCheck
        If r.Value = sGroupOn Then
            persons(personCount).title = r.Offset(0, iTitle - 1)
            persons(personCount).surname = r.Offset(0, iSurname - 1)
            personCount = personCount + 1
        End If
    Next r
    
    andSymbol = " " & Trim(andSymbol) & " "
    
    If personCount > 0 Then
        ' Put the people in the array in the correct order
        If personCount > 1 Then Call SortTitles(persons, personCount)
        
        Dim concatString As String
        concatString = persons(0).title
        
        If personCount > 1 Then
            Dim i As Integer
            For i = 1 To personCount - 1
                If persons(i).surname = persons(i - 1).surname Then
                    concatString = concatString & andSymbol & persons(i).title
                Else
                    concatString = concatString & " " & persons(i - 1).surname & andSymbol & persons(i).title
                End If
            Next i
        End If
        
        concatString = concatString & " " & persons(personCount - 1).surname
        SALULOOKUP = Trim(concatString)

    Else
        ' personCount < 1 therefore didn't find any people with a matching ref
        SALULOOKUP = "#N/A"
    End If
    
End If

End Function


Private Sub SortTitles(ByRef persons() As person, ByVal personCount As Integer)
' Sorts the array by their titles i.e. Mr before Mrs; Lord before Mr etc etc

Dim noChanges As Boolean
Do
    noChanges = True
    Dim i As Integer
    For i = 1 To personCount - 1
        If ScoreTitle(persons(i).title) < ScoreTitle(persons(i - 1).title) Then
            Call SwopElements(persons, i - 1, i)
            noChanges = False
        End If
    Next i
Loop Until (noChanges Or personCount = 2)

End Sub


Private Function ScoreTitle(sTitle As String) As Integer
' Lower iPriority scores will be sorted to first

Dim iPriority As Integer

Select Case sTitle
Case "Lord"
    iPriority = 10
Case "Sir"
    iPriority = 20
Case "Dr"
    iPriority = 30
Case "Prof"
    iPriority = 40
Case "Rev"
    iPriority = 50
Case "Mr"
    iPriority = 60
Case "Lady"
    iPriority = 70
Case "Mrs"
    iPriority = 80
Case "Ms"
    iPriority = 90
Case "Miss"
    iPriority = 100
End Select

ScoreTitle = iPriority

End Function


Private Sub SwopElements(ByRef persons() As person, i1 As Integer, i2 As Integer)
' Swops two elements in a person array of any size

    Dim temp As person
    
    temp.title = persons(i1).title
    temp.surname = persons(i1).surname
    
    persons(i1).title = persons(i2).title
    persons(i1).surname = persons(i2).surname
    
    persons(i2).title = temp.title
    persons(i2).surname = temp.surname

End Sub

Thanks for any feedback!
/AJ
 

Excel Facts

Select a hidden cell
Somehide hide payroll data in column G? Press F5. Type G1. Enter. Look in formula bar while you arrow down through G.
Adam,

You appear not to have included the declaration for the user defined type, person.
 
Upvote 0
Oh yes. Schoolboy error. Thank you.

Code:
Private Type person
    surname As String
    title As String
End Type

/AJ
 
Upvote 0
Adam,

Having added the declaration, before my previous post, I forgot to mention that your UDF does exactly what it says on the tin !
I took a look at it purely out of general interest but there must be folk out there who would find it useful.

I wonder whether or not you might consider the following minor code change to be of any benefit?

Rich (BB code):
Private Function ScoreTitle(sTitle As String) As Integer
' Lower iPriority scores will be sorted to first


Dim iPriority As Integer


Select Case sTitle
Case "Lord"
    iPriority = 10
Case "Sir"
    iPriority = 20
Case "Dr"
    iPriority = 30
Case "Prof"
    iPriority = 40
Case "Rev"
    iPriority = 50
Case "Mr"
    iPriority = 60
Case "Lady"
    iPriority = 70
Case "Mrs"
    iPriority = 80
Case "Ms"
    iPriority = 90
Case "Miss"
    iPriority = 100
Case Else
iPriority = 110
End Select


ScoreTitle = iPriority




End Function

Comparative results....

Excel 2007
ABCDEFG
1Room NoTitleSurnameRoom NoSalutationRevised ?
21MrJames1Adam & Mr & Mrs JamesMr & Mrs & Adam James
31MrsJames2Fifi (The Poodle) & Lord Smith & Lady JonesLord Smith & Lady Jones & Fifi (The Poodle)
41AdamJames4Mrs SutcliffeMrs Sutcliffe
52LordSmith5Mr & Mrs & Miss BradyMr & Mrs & Miss Brady
62LadyJones6Charlotte & Dr & Mrs WayDr & Mrs Way & Charlotte
72Fifi(The Poodle)
84MrsSutcliffe
95MrBrady
105MrsBrady
115MissBrady
126DrWay
136MrsWay
146Charlotte
Sheet8
 
Upvote 0
Adam,

One last observation.
If perchance any of the titles attract a leading or trailing space because the data is entered by somebody whose typing skills are as poor as mine then the Select Case code will not allocate the priorities as you intend.
This can be avoided if you add the line using the TRIM function.

Rich (BB code):
Private Function ScoreTitle(sTitle As String) As Integer' Lower iPriority scores will be sorted to first


sTitle = Trim(sTitle)


Dim iPriority As Integer


Select Case sTitle
Case "Lord"
    iPriority = 10
Case "Sir"
    iPriority = 20
Case "Dr"
    iPriority = 30
Case "Prof"
    iPriority = 40
Case "Rev"
    iPriority = 50
Case "Mr"
    iPriority = 60
Case "Lady"
    iPriority = 70
Case "Mrs"
    iPriority = 80
Case "Ms"
    iPriority = 90
Case "Miss"
    iPriority = 100
Case Else
iPriority = 110
End Select


ScoreTitle = iPriority




End Function

Hope that helps.
 
Upvote 0
Yeah spot on. Actually that is a fairly common problem as well as a lot of data is taken from legacy DB systems that output some crazy stuff at times!

Thank you.

/AJ
 
Upvote 0
Yeah spot on. Actually that is a fairly common problem as well as a lot of data is taken from legacy DB systems that output some crazy stuff at times!

If you want to go a little further then...

Code:
sTitle = Trim(WorksheetFunction.Clean(WorksheetFunction.Substitute(sTitle, Chr(160), "")))

will remove most 'invisible' characters from the sTitle string.
 
Upvote 0

Forum statistics

Threads
1,215,022
Messages
6,122,726
Members
449,093
Latest member
Mnur

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top