Lets say I have a text Howard Johnson, 21 (USA)
I want to get the substring of the text Johnson.
I could do this with InStr and Microsoft.VisualBasic.Left Or Mid, But I always found this method rather tedious and I want to know if there is another easier method to do this.
Dim myText As String = "Howard Johnson, 21 (USA)"
Dim textIWant As String = InStr(1, myText, Chr(32))
Dim LastName As String = Mid(myText, textIWant + 1, textIWant)
'Output: Johnson
Any suggestions?
Try this code - it uses the IndexOf function of a String to locate the first instance of a character within that String.
For a surname, the example code is looking for the first space and the first comma and taking the text in between. The assumption is that the surname is always delimited that way.
For the country, the example code is looking for the first ( and the last ) and taking the text in between. The assumption is that the country is always in round brackets.
Here's the code:
Sub Main()
Dim Input As String
Dim Surname As String
Dim Country As String
Input = "Howard Johnson, 21 (USA)"
Surname = Input.Substring(Input.IndexOf(" ") + 1, Input.IndexOf(",") - Input.IndexOf(" ") - 1)
Country = Input.Substring(Input.IndexOf("(") + 1, Input.IndexOf(")") - Input.IndexOf("(") - 1)
Console.WriteLine(Surname)
Console.WriteLine(Country)
Console.ReadKey()
End Sub
It will also work for people who have spaces in their surname e.g.:
Input = "Albert del Rosario, 75 (Phillipines)"
Surname = Input.Substring(Input.IndexOf(" ") + 1, Input.IndexOf(",") - Input.IndexOf(" ") - 1)
Will output
del Rosario
Dim myText = "Howard Johnson, 21 (USA)"
Dim LastName = myText.Split(" "c, ","c)(1) ' myText.Split(" "c, ","c) gives array {"Howard", "Johnson", "", "21", "(USA)"}
Related
How do I parse multiple values out of a single column?
The problem is that multiple values are surrounded by extraneous (for my purposes) data.
Example:
Select * from my_table:
Fname Lname Data
Fred Smith #3aXXXX;Name:AA;#43deXXXX;Name:BB;#5433ed9;NAME:ABC;*#!XXXXXXXX;NAME:MyPetDog;##IDXXXX
For the Data column, I want to extract all the values following the "Name:" fields from the column. That would be the text following "Name:" and preceding ";". In the example above:
Select Fname, Lname, [DATA] from my_table
Fname Lname [*Parsed* DATA]
Fred Smith AA,BB, ABC, MyPetDog
Solving the above Would be a tremendous help. However, what I would really like to do a lookup/replace (SWITCH, etc.) each of the values returned from the string:
Fname Lname [Translated DATA]
Fred Smith Airport, Bus Station, Restaurant, FIDO
I apologize for using notional data. My actual script (on another network) involves several table joins to get to the column DATA. I just can't figure out how to extract the specific values from this large string (other that to extract the full data set and use AWk or MS Excel to cleanup the data afterwards).
Appreciate any assistance or tips on solving this.
Kevin L.
I would recommend creating a small VBA function that takes the "ugly" data and splits it out using the Split function. Something like:
Public Function fSplitData(strData As String) As String
Dim aData() As String
Dim lngLoop1 As Long
aData = Split(strData, ";")
For lngLoop1 = LBound(aData) To UBound(aData)
If Left(aData(lngLoop1), 5) = "Name:" Then
fSplitData = fSplitData & Mid(aData(lngLoop1), 6) & ","
End If
Next lngLoop1
If Right(fSplitData, 1) = "," Then fSplitData = Left(fSplitData, Len(fSplitData) - 1)
End Function
This gives the required output of:
AA,BB,ABC,MyPetDog
And, rather than just concatenating the extracted value, you could use a recordset to get the data from a lookup table. In your case, as you only have 8 values, you could just use If within the code:
Public Function fSplitData(strData As String) As String
Dim strLookup As String
Dim aData() As String
Dim lngLoop1 As Long
aData = Split(strData, ";")
For lngLoop1 = LBound(aData) To UBound(aData)
If Left(aData(lngLoop1), 5) = "Name:" Then
strLookup = Mid(aData(lngLoop1), 6)
If strLookup = "AA" Then
fSplitData = fSplitData & "Airport,"
ElseIf strLookup = "BB" Then
fSplitData = fSplitData & "Bus Station,"
ElseIf strLookup = "ABC" Then
fSplitData = fSplitData & "Restaurant,"
ElseIf strLookup = "MyPetDog" Then
fSplitData = fSplitData & "FIDO,"
End If
End If
Next lngLoop1
If Right(fSplitData, 1) = "," Then fSplitData = Left(fSplitData, Len(fSplitData) - 1)
End Function
You can then use this function in a query, just like you would use a standard Access function. So your SQL would look like:
SELECT
FName,
LName,
Data,
fSplitData([Data]) AS TranslatedData
FROM Table1;
Thanks to #Applecore, I have a almost working solution (though not likely the best solution):
SELECT Fname,
Lname,
SWITCH(data like "*AA*","Airport")&", "&
SWITCH(data like "*BB*", "Bus Station")&", "&
SWITCH(data like "*ABC*", "Restaurant")&", "&
SWITCH(data like "*MyPetDog*","FIDO") as DATA
Fname Lname [Translated DATA]
Fred Smith Airport, Bus Station, Restaurant, FIDO
The only problem is,if a value is NOT there, then I get extra commas. For example, if BB is the only value present, then I get:
Fname Lname [Translated DATA]
Fred Smith , Bus Station, ,
Do as #AppleCore suggests, use an external function to avoid the mess.
SELECT
Fname,
Lname,
CleanField([Data]) AS TranslatedData
FROM
my_table;
Copy-paste the function (using Select Case .. for the conversion) into a new module, go to menu Debug, Compile, and save the module as, say, Module1_:
Public Function CleanField(ByVal Value As String) As String
Dim Parts As Variant
Dim Index As Integer
Dim Part As String
Dim Text As String
Parts = Split(";" & Value, ":")
For Index = LBound(Parts) To UBound(Parts)
Part = Split(Parts(Index), ";")(0)
Select Case Part
Case Is = "AA"
Part = "Airport"
Case Is = "BB"
Part = "Bus station"
Case Is = "ABC"
Part = "Restaurant"
Case Is = "MyPetDog"
Part = "FIDO"
End Select
If Part <> "" Then
If Text <> "" Then
Text = Text & ", "
End If
Text = Text & Part
End If
Next
CleanField = Text
End Function
Example:
Fname Lname TranslatedData
------- ------- --------------------------------------
Fred Smith Airport, Bus station, Restaurant, FIDO
George Olsen Airport, Restaurant, Bus station, FIDO
Tina Doe Restaurant, Bus station, FIDO
I have a string and I want to get the words in parentheses and list them:
I'm (Kid J)
From (Detroit), (Michigan)
I tried the cod below, but this code only lists two words :
For Each line As String In TextBox1.Lines
Dim i As Integer = line.IndexOf("(")
Dim f As String = line.Substring(i + 1, line.IndexOf(")", i - 1) - i - 1)
TextBox2.AppendText(f + vbCrLf)
Next
the result with this cod is this:
Kid J
Detroit
You can use Regex:
Dim text = "I'm (Kid J)
From (Detroit), (Michigan)"
Dim matches = From match In Regex.Matches(text, "\(([^)]*)\)")
Select match.Groups(1).Value
Console.Write(String.Join(",", matches))
outputs:
Kid J,Detroit,Michigan
Here's the regex with some explanations:
https://regex101.com/r/13ME3n/1
Let’s say that this is my string:
Sam, III , Adams
Here Sam, III is first name and Adams is the the Last Name, I wanna separate first name and last name. For that I did:
txtbox.Text.Split(",")
But it is separating Sam, III, Adams into 3 parts. Can someone let me know how to separate first name and last name if we any extra ',' in either first name or last name?
Instead of String.Split you could use IndexOf to find the index of the first comma and then Substring to get the parts on either side of the comma:
Dim text = "Sam, III, Adams"
Dim index = text.IndexOf(",")
Dim firstName = text.Substring(0, index)
Dim secondName = text.Substring(index + 1)
In either first name or last name
Simple answer: no. "Sam, III, Adams" - is that "Sam III" "Adams" or "Sam" "III Adams" - how can the application possibly know other than knowing all possible names or variations for the comma part. I'm guessing this person's name would actually be "Sam Adams, the Third" - not sure why their first name would be "Sam III".
The comments to another answer suggest you do have specific rules to use when there are commas - if you can state the requirements clearly when there are multiple commas, then a more specific answer can be provided,
It appears that you may need a set of rules, based on how many commas, eg:
Dim firstname = ""
Dim surname = ""
Dim text = "Sam, III, Adams"
Dim parts = text.Split(",")
If parts.Length = 1 Then
firstname = ""
surname = parts(0)
else If parts.Length = 2 Then
firstname = parts(0)
surname = parts(1)
else If parts.Length = 3 Then
' Rule from question sample, comma in firstname (makes no sense to me, but that's how it's in the question)
firstname = parts(0) + ", " + parts(1)
surname = parts(2)
else If parts.Length = 4 Then
firstname = parts(0) + ", " + parts(1)
surname = parts(2) + ", " + parts(3)
End If
(or use a select case)
If you can simplify the rules, then it's much cleaner, eg:
All commas in surname:
firstname = string.Join(", ", parts.Take(parts.length-1))
surname = parts(parts.length)
All commas in firstname:
firstname = parts(0)
surname = string.Join(", ", parts.Skip(1))
This is a sample data contained in one cell:
2014/08/19 12:59 John Doe
add sample#hotmail.com
I need to extract the name in the text. I know that it is always placed after the datetime stamp.
My idea is to find the position of ":" and add 4 thus getting the position of the first letter of the first name:
colonLoc = InStr(sampleData, ":")
firstLetterLoc = colonLoc + 4
How can I get the first and last name after that?
Here is a one liner to achieve what you want.
debug.print Mid(Split(Split(Range("A1").Value, Chr(10))(0), ":")(1), 3)
EDIT:
Actually you don't need VBA for this. You can use Excel formulas as well
=MID(A1,FIND(":",A1)+3,FIND(CHAR(10),A1)-(FIND(":",A1)+3))
This works even for names with spaces:
Function ExtractName(str As String) As String
Dim i As Long
Dim splitStr() As String
Dim nameParts() As String
splitStr = Split(str, " ")
ReDim nameParts(LBound(splitStr) To UBound(splitStr) - 4)
For i = LBound(nameParts) To UBound(nameParts)
nameParts(i) = splitStr(i + 2)
Next i
ExtractName = Join(nameParts, " ")
End Function
What this effectively does is remove four substrings: the date, the time, the add bit, and the e-mail address. Everything else in the middle is assumed to be part of the name.
Example usage:
Debug.Print ExtractName("2014/08/19 12:59 John Doe add sample#hotmail.com")
Debug.Print ExtractName("2014/08/19 12:59 Johan Sebastian Bach add sample#hotmail.com")
Debug.Print ExtractName("2014/08/19 12:59 Fuh Wei Guo Tang add sample#hotmail.com")
Debug.Print ExtractName("2014/08/19 12:59 Jens von dem Hagen add sample#hotmail.com")
Debug.Print ExtractName("2014/08/19 12:59 José Manuel de Santiago Itthuralde add sample#hotmail.com")
EDIT Now you say your input string is split over two lines... This works for me with the input you specify:
Function ExtractName(str As String) As String
Dim i As Long
Dim splitStr() As String
Dim nameParts() As String
splitStr = Split(Split(str, vbLf)(0), " ")
ReDim nameParts(LBound(splitStr) To UBound(splitStr) - 2)
For i = LBound(nameParts) To UBound(nameParts)
nameParts(i) = splitStr(i + 2)
Next i
ExtractName = Join(nameParts, " ")
End Function
It's like this:
Option Explicit
Public Sub Playground()
Const SampleData As String = "2014/08/19 12:59 John Doe add sample#hotmail.com"
Dim Parts() As String
Dim FirstName As String
Dim LastName As String
Parts = Split(SampleData)
FirstName = Parts(2)
LastName = Parts(3)
Debug.Print FirstName
Debug.Print LastName
End Sub
For more complicated cases (e.g. spaces in names) you might have to tweak it a little bit.
This will give you firstname (assuming there is only 1), lastname (all other names) and email in a variant array
Option Explicit
Public Function Name(source As String) As Variant
Dim breakup As Variant
breakup = Split(source, ":")
breakup = Split(Mid(breakup(1), 4), " ")
Dim i As Integer
Dim FirstName As String
FirstName = breakup(0)
Dim LastName As String
For i = 1 To UBound(breakup) - 2
LastName = LastName & " " & breakup(i)
Next
LastName = Mid(LastName, 2)
Dim Email As String
Email = breakup(UBound(breakup))
Name = Array(FirstName, LastName, Email)
End Function
sampleData = "2014/08/19 12:59 John Doe add sample#hotmail.com"
New_String = Split(sampleData)
sName = New_String(2) & " " & New_String(3)
Debug.Print sName
Easy as that :)
I am trying to obtain the string to the right of the delimiter "|" and anything to the left can be ignored.
I tried the following, but it gives me the values to the left
Dim s As String = "John Smith | 09F2"
Console.WriteLine(s.Substring(0, s.IndexOf("|")))
Console.WriteLine(s.Split(CChar("|"))(0))
Console.ReadKey()
Result is: John Smith. I want the 09F2 value.
I also tried the following lines of code:
Dim strEmployeeInfo As String = cmbSelectEmployee.Text
Dim employeeID = Microsoft.VisualBasic.Right(strEmployeeInfo, strEmployeeInfo.IndexOf("|"))
But the result of that is Smith | 09F2. Again I only need the 09F2
When you split on the | character, the resulting array will have "John Smith " in the first position, and " 09F2" in the second position. So you need to access the second position. Since it's 0-based pass in 1 to access the second position. Next, trim the result to get rid of any additional spaces:
Dim s As String = "John Smith | 09F2"
Dim split As String() = s.Split("|"c)
Dim result As String = split(1).Trim()
Try this:
Console.WriteLine(s.Substring(s.IndexOf("|") + 1));
Suppose you have more than one "|" in your string and you want the last part after the last "|", you can use this and also it works for the above example:
Dim SArray() As String = s.Split("|"c);
//if necessary, check the length of SArray() for correctness
Console.WriteLine(SArray(SArray.Length - 1));
I'd go with this:
Dim s As String = "John Smith | 09F2"
Console.WriteLine(s.Split("|").Last().Trim())