Reorder parts of a name with a suffix - excel

I need help on vba code to reorder the parts of a name. Sometimes there is a suffix (Jr, Sr, I, II, III, IV), and that is the part I can't figure out. There is no list that I need to loop thru. The elements of the name could look like this: Johnson, Joseph Allen Jr
This code works for getting the last name moved to the end, but now I need to trim & move the suffix to the right after the last name.
Range("A1") = Trim(StrReverse(Split(StrReverse(Range("A1")), ",")(0)) & " " _
& StrReverse(Split(StrReverse(Range("A1")), ",")(1)))
Result: Joseph Allen Jr Johnson
Result Required: Joseph Allen Johnson Jr
Thanks for any help!

So if your inputs are like Johnson, Joseph Allen Jr then you could set up an array/collection with the suffixes you want to check against. Then before you move the last name use
Dim i as Variant
Dim suffixArray as String()
Dim nameString as String
Dim suffixString as String
Dim arrayEntryLength as Long
suffixArray(0) = "Jr"
suffixArray(1) = "Sr"
suffixArray(2) = "I"
suffixArray(3) = "II"
...
for each i in suffixArray
nameString = "Johnson, Joseph Allen Jr" 'or use Cells(1,"a").value
arrayEntryLength = len(suffixArray(i))
if Right(nameString, arrayEntryLength) = suffixArray(i) then
suffixString = suffixArray(i)
nameString = left(nameString, len(nameString)-arrayEntryLength)
end if
next i
'move the last name of nameString
nameString = nameString & " " & suffixString
'rest of code

The full name is a unparsed string and manipulating "Suffix" as mentioned above by Chris H may be a suitable way. Here is Fullname content model in Outlook contact Item: https://learn.microsoft.com/en-us/office/vba/api/outlook.contactitem.fullname. Building an array of known suffixes will solve this in general. Watch out: the suffix may such as King Louis XVII, etc. is some historical context.

Related

VB.net Trim function

I have an issue with trim the string method NOT working completely I have reviewed MS Docs and looked of forums but with no luck... It's probably something simple or some other parameter is missing. This is just a sample,
Please note I need to pick up text before and after #, hence than I was planning to use # as a separator. Trim start # #, Trim End # #. I can't use The last Index or Replace per my understanding they have no direction. But perhaps I am misunderstood MS docs regards to trim Start and End as well...
thanks!
Dim str As String = "this is a #string"
Dim ext As String = str.TrimEnd("#")
MsgBox(ext)
ANSWER:
I found a solution for my problem, if you experience similar please see below:
1st: Trim end will NOT scan for the "character" from the Right as I originally thought it will just remove it from the right.... A weak function I would say:). IndexOf direction ID would be a very simple and helpful. Regards My answer was answered by Andrew, thanks!
Now there is another way around it if you try to split a SINGLE String INTO - QTY based on CHARACTER separation and populate fields accordingly.
Answer is ArrayList. Array List will ID each String so you can avoid repeated populations and etc. After you can use CASE or IF to populate accordingly.
Dim arrList As New ArrayList("this is a # string".Split("#"c)) ' Will build the list of your strings
Dim index As Integer = 1 ' this will help us index the strings 1st, 2nd and etc.
For Each part In arrList 'here we are going thru the list
Select Case index ' Here we are identifying which field we are populating
Case 1 '1st string(split)
MsgBox("1 " & arrList(0) & index) '1st string value left to SPLIT arrList(0).
Case 2 '2nd string(split)
MsgBox("2 " & arrList(1) & index) '2nd string value left to SPLIT arrList(1).
End Select
index += 1 'Here we adding one shift thru strings as we go
Next
Rather than:
Dim str As String = "this is a #string"
Dim ext As String = str.TrimEnd("#")
Try:
Dim str As String = "this is a #string"
Dim ext As String = str.Replace("#", "")
Dim str As String = "this is a #string"
Dim parts = str.Split("#"c)
For Each part in parts
Console.WriteLine($"|{part}|")
Next
Output:
|this is a |
|string|
Maybe there is a better way as we know there are multiple things to do the same thing.
The solution I used is below:
Dim arrList As New ArrayList("this is a # string".Split("#"c)) ' Will build the list of your strings
Dim index As Integer = 1 ' this will help us index the strings 1st, 2nd and etc.
For Each part In arrList 'here we are going thru the list
Select Case index ' Here we are identifying which field we are populating
Case 1 '1st string(split)
MsgBox("1 " & arrList(0) & index) '1st string value left to SPLIT arrList(0).
Case 2 '2nd string(split)
MsgBox("2 " & arrList(1) & index) '2nd string value left to SPLIT arrList(1).
End Select
index += 1 'Here we adding one shift thru strings as we go
Next

How to find values that aren't 100% duplicated?

I have a list of people getting aid from my organization.
Some register their names with different spelling or different order.
Here is an example
**Names** **ID**
Ahmed mohammed Saleh 3576158946 Personal ID
Waleed Khalid Ali 5478698645 Personal ID
Fatima Nader Aljalal 4684325986 Personal ID
Hussan Huessien Ahmed 778569 Family ID
*Ahmed Mohamed Salah* 698745 Family ID
*Waleed Ali Khalid* No ID
The last two in the list have registered twice.
My data has 4000 rows and I have to find the partial duplicates.
One way to reduce the difficulty of the task is to hash the names to a sorted string of lowercase characters with duplicate characters, spaces and vowels removed. You could then compare the hashed names to determine similarity. In the example below we are fortunate that we get exact matches but it would not be impossible to write a further function that checked if the hashed names differed by one, two or more characters, and in fact that the original names were a reasonable match.
Option Explicit
Private Type State
CharArray As Variant
End Type
Private s As State
Public Sub test()
Initialise
Debug.Print "Ahmed mohammed Saleh", ConvertNameToHash("Ahmed mohammed Saleh")
Debug.Print "Ahmed Mohamed Salah", ConvertNameToHash("Ahmed Mohamed Salah")
Debug.Print "Waleed Khalid Ali", ConvertNameToHash("Waleed Khalid Ali")
Debug.Print "Waleed Ali Khalid", ConvertNameToHash("Waleed Ali Khalid")
End Sub
Public Sub Initialise()
s.CharArray = Split("b,c,d,f,g,h,j,k,l,m,n,p,q,r,s,t,v,w,x,y,z", ",")
End Sub
Public Function ConvertNameToHash(ByVal ipName As String) As String
Dim myChars As String
Dim myName As String
myName = LCase$(ipName)
Dim myChar As Variant
For Each myChar In s.CharArray
If InStr(myName, myChar) > 0 Then
myChars = myChars & myChar
End If
Next
ConvertNameToHash = myChars
End Function
The output from the above code was
Ahmed mohammed Saleh dhlms
Ahmed Mohamed Salah dhlms
Waleed Khalid Ali dhklw
Waleed Ali Khalid dhklw

Using Split To Separate only 1st instance-VBA

I have a situation where I need to separate a statement pulled from SAP based on the word "Caller" The issue is that this word is used multiple times throughout the statement but I need it to only cut off the 1st sentence leading up to the 1st "Caller". Is there a way to have split separate these words out and then recombine everything split except the (0) instance.
Here is my code that I am using right now.
Description_Rough = session.findById("wnd[0]/usr/tabsTAB_GROUP_10/tabp10\TAB01/ssubSUB_GROUP_10:SAPLIQS0:7235/subCUSTOM_SCREEN:SAPLIQS0:7212/subSUBSCREEN_4:SAPLIQS0:7715/cntlTEXT/shellcont/shell").Text
Descrption_Final = Split(Description_Rough, "Caller")(1)
And the statement being pulled as description_rough is
08.08.2018 21:53:55 UTC "Name" (Numbers) Phone #########
17.07.2018 16:25:47 AAAAAA AAAAAA (AAAAAA)
Caller is patient using device. Caller reports that she has been using
current device for about 9 days and that the problems arose with the device. Caller reports that she monitors the device
each dose and does not recall what dose was in the device before it went to all red. Patient to return affected device to
Company; mail order pharmacy to replace to patient; Company to replace to
Pharmacy.
What I am looking for is everything beginning at "Caller is patient using device."
Simplest way to do it in my opinion
Sub Sample()
Dim Descrption_Final As String
Dim pos As Long
Descrption_Final = "17.07.2018 16:25:47 AAAAAA AAAAAA (AAAAAA) Caller is patient Blah Blah....."
pos = InStr(1, Descrption_Final, "caller", vbTextCompare)
If pos > 0 Then Debug.Print Mid(Descrption_Final, pos)
'~~> Output: Caller is patient Blah Blah.....
End Sub
And if you want everything before Caller is patient Blah Blah..... then use 0 instead of 1
Split(Description_Rough, "Caller")(0)
Example
Sub Sample()
Dim Descrption_Final As String
Dim pos As Long
Descrption_Final = "17.07.2018 16:25:47 AAAAAA AAAAAA (AAAAAA) Caller is patient Blah Blah....."
Debug.Print Split(Descrption_Final, "Caller")(0)
'~~> Output: 17.07.2018 16:25:47 AAAAAA AAAAAA (AAAAAA)
End Sub
This should work. It just starts from the second occurrence of "Caller" and pieces it all back together from there.
Description_Rough = "Caller is patient using device. Caller reports that..."
Dim temp As Variant
temp = Split(Description_Rough, "Caller")
Dim Description_Final As String
Dim i As Long
For i = LBound(temp) + 1 To UBound(temp)
Description_Final = Description_Final & "Caller" & temp(i)
Next i

regex for Excel to remove all but specific symbols after a specific symbol?

I have stings like this which are addresses, e.g.:
P.O. Box 422, E-commerce park<br>Vredenberg<br><br><br>Curaçao
Adelgatan 21<br>Malmö<br><br>211 22<br>Sweden
Läntinen Pitkäkatu 35 A 15<br>Turku<br><br>20100<br>Finland
I am interested in Country only. Country always comes last after a <br> tag.
Note, that there can be several such tags preceding this last value (e.g. 1st example string).
Is there a good way to do a formula may ve along those lines:
Identify end of string
Loop a character back until one reaches ">" character
Cut everything else (including the ">" encountered)
You don't need RegEx to do this if it's always the last part of the string.
You can get it with String modifiers doing
Sub Test()
Dim str As String, str1 As String, str2 As String
Dim Countries As String
str = "P.O. Box 422, E-commerce park<br>Vredenberg<br><br><br>Curaçao"
str1 = "Adelgatan 21<br>Malmö<br><br>211 22<br>Sweden"
str2 = "La¨ntinen Pitka¨katu 35 A 15<br>Turku<br><br>20100<br>Finland"
Countries = Right(str, Len(str) - InStrRev(str, "<br>") - 3)
Countries = Countries + vbNewLine + Right(str1, Len(str1) - InStrRev(str1, "<br>") - 3)
Countries = Countries + vbNewLine + Right(str2, Len(str2) - InStrRev(str2, "<br>") - 3)
MsgBox Countries
End Sub
Obviously this will need to be updated for how your data set is stored. You can loop through the dataset and use the string modifier on each line
A formula works too. If a string in A1, write in B1:
=TRIM(RIGHT(SUBSTITUTE(A1,"<br>",REPT(" ",100)),100))
Modified using an approach taken from here:
https://exceljet.net/formula/get-last-word

Excel formula to rearrange LastName, Firstname MiddleInitial to FirstName Lastname

I need some help with a formula to rearrange names. I've found lots of formulas that work in some cases, but none that can handle all of the cases I encounter.
Briefly, here is the list of names, and the desired output:
Original names Desired Output
John, James J James John
Junior, Lake Lake Junior
Mitchel, Fields M Fields Mitchel
Rothschild Jr., Michael K Michael Rotschild
Sally, Sue L Sue Sally
Rinkel, Michael Michael Rinkel
Rivel, Nicholas L Nicholas Rivel
Hurwitz Sr., Susan Susan Hurwitz
The formula I have so far is: =TRIM(PROPER(TRIM(IF(ISERROR(FIND(",",A1,1)),A1,MID(A1,FIND(",",A1,1)+1,IF(ISERROR(FIND(" ",A1,FIND(",",A1,1)+2)),LEN(A1),FIND(" ",A1,FIND(",",A1,1)+2))-FIND(",",A1,1))))&" "&LEFT(A1,IF(ISERROR(FIND(",",A1,1)),LEN(A1),FIND(",",A1,1)-1))))
Its cobbled together from some other formulas I have found, and eliminates middle initials if they are present, but not the Sr. or Jr.'s if they are present.
There are so many nuances to parsing names that just as soon as you think you have covered all possibilities, there are new ones coming up. If you keep a User Defined Formula (aka UDF), you can quickly add new coding processes to meet new problems.
Public Function fcn_First_Last_Name(sNAM As String)
Dim sTMP As String, v As Long, vDELs As Variant, vNAMs As Variant
sTMP = Application.Trim(sNAM)
vDELs = Array(" Jr.", " Sr.", " III", " II")
sTMP = Replace(sTMP, Chr(160), Chr(32))
For v = LBound(vDELs) To UBound(vDELs)
sTMP = Replace(sTMP, vDELs(v), vbNullString, compare:=vbTextCompare)
Next v
If Asc(Mid(sTMP, Len(sTMP) - 1, 1)) = 32 Then sTMP = Trim(Left(sTMP, Len(sTMP) - 1))
vNAMs = Split(sTMP, Chr(44))
If CBool(UBound(vNAMs)) Then
fcn_First_Last_Name = vNAMs(UBound(vNAMs)) & Chr(32) & vNAMs(LBound(vNAMs))
Else
fcn_First_Last_Name = vNAMs(UBound(vNAMs))
End If
End Function
That should get you started. It should also prove to be a good learning experience as you add new routines to cover new difficulties.
Once you have that in a VBA code module sheet, use it just like any other worksheet formula. Example:
        
Another possibility, but very clunky:
=MID(A2,FIND(", ",A2,1)+2,IFERROR((FIND(" ",A2,FIND(", ",A2,1)+2)-4)-FIND(", ",A2,1)+2,LEN(A2)))&" "&IFERROR(LEFT(A2,FIND(" ",LEFT(A2,FIND(", ",A2,1)-1))-1),LEFT(A2,FIND(", ",A2,1)-1))

Resources