I have Full name Field that I would like to split and remove the middle name from the name.
Names are like:
Smith,James D - > Result be : Smith, James
Doe,John Snow -> Result be: Doe, John
Here is what I did but not sure what I am missing to remove the Middle name
FName: Mid([Employee] & "",InStr(1,[Employee] & " ",",")+1)
Lname: Left([Employee] & "",InStr(1,[Employee] & "",",")+(InStr(1,[Employee] & "",",")>0))
Smith,James D - > I get -> FName: James D
Doe,John Snow -> I get -> FName: John Snow
Consistency of structure is critical in string manipulation. Assuming there will always be 3 and only 3 parts to each name and 3rd part is middle name/initial and there is no space following comma, consider:
LastFirst: Left([Employee], InStrRev([Employee]," ")-1
Last: Left([Employee], InStr([Employee],",")-1)
First: Mid(Left([Employee], InstrRev([Employee]," ")-1), Instr([Employee],",")+1)
Middle: Mid([Employee], InStrRev([Employee], " ")+1)
If any of the assumptions do not hold, then build a VBA custom function.
Call that function from query or textbox. Other answers are showing excellent methods of parsing name string with VBA function.
The more variation from assumptions, the more complicated the code. Enough variation and this could become virtually impossible to automate.
The following simple function removes Middle name and returns only Last, First even when there is no Middle name or multiple Middle Names in FullName:
Public Function FixName(fullName) As String
Dim last() As String
Dim first() As String
last = Split(fullName, ",")
FixName = last(0)
first = Split(last(1), " ")
FixName = FixName & ", " & first(0)
End Function
Haven't tested but wouldn't this work for you? Within a vba public function.
'First word being first name
FName= split([employee], ",")(0)
'Second word being the last name. This will throw `indexOutOfRange` error if employee name is only one word. Use `on error resume next` to silently ignore?
LName = split(replace([employee], ",", " "))(1)
You cannot use split directly in ms access sql but that doesn't stop you to create a custom split function.
Public function FnSplit(text as variant, index as integer, optional d as string = " ") as string
If nz(len(text),0) = 0 then exit function
On error resume next
FnSplit = split(text,d)(index)
End function
And use in your sql
Select
FnSplit([employee],0) as fName,
FnSplit(replace([employee], ",", " "),1) as lName
From
Your table
Obviously these are just another way of doing the same work as previous answers
Related
I'm working on changing an Access 2010 report. There is a portion of the report that reads in Raw Data from a SharePoint field called "Notes" that has comments for each record. Within the "notes" field, there can be several sentences. I need to find a way to separate those sentences into a bullet point per sentence in my report.
I'm trying to come up with a clever way to do so. I can get the data entry folks to use a symbol of some sort in the raw that signifies the need for a new bullet. This way, in my Report Expression (or perhaps via VBA), I can get it separated... but how?
Any thoughts?
The memo data field in MS Access can be set to Rich Text as a property, so:
UPDATE Table1
SET Table1.AMemo = "<ul><li>" &
IIf(InStr([AMemo],".")>0,
Replace(Mid([AMemo],1,Len([AMemo])-1),".","</li>"),[AMemo]) & "</li></ul>"
In its most rudimentary form you could do something like the following. Is splits the [Notes] text on ". " and creates a separate "point" for each sentence.
Sample Data: [SharePointData]
SlideNumber Notes
----------- ------------------------------------
1 Title slide.
2 Brief overview. Just the highlights.
3 More stuff.
VBA Code:
Option Compare Database
Option Explicit
Public Function SplitNoteText(RawText As Variant) As Variant
Dim rtn As Variant, StringArray() As String, Point As Variant
Const BulletChar = "-"
rtn = Null
If Not IsNull(RawText) Then
rtn = ""
StringArray = Split(RawText, ". ", -1, vbBinaryCompare)
For Each Point In StringArray
If Len(Point) > 0 Then
If Len(rtn) > 0 Then
rtn = rtn & vbCrLf & vbCrLf
End If
rtn = rtn & BulletChar & " " & Point
If Right(Point, 1) <> "." Then
' add back the period that got "consumed" in the Split
rtn = rtn & "."
End If
End If
Next
End If
SplitNoteText = rtn
End Function
Test query:
SELECT SlideNumber, Notes, SplitNoteText(Notes) AS Points FROM SharePointData;
Results:
SlideNumber Notes Points
----------- ------------------------------------ ----------------------
1 Title slide. - Title slide.
2 Brief overview. Just the highlights. - Brief overview.
- Just the highlights.
3 More stuff. - More stuff.
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())
I am attempting to write a program in VB.net which will output some values in to a text file. Please be patient with me as I am very new to VB.net.
What I have so far is below:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim str As String
For Each File As String In System.IO.Directory.GetFiles(TextBox1.Text)
str = str & File & "|" & System.IO.Path.GetFileNameWithoutExtension(File).Split("-")(0).Trim & "|" & System.IO.Path.GetFileNameWithoutExtension(File).Split("-")(0).Trim & "||" & DateTimePicker1.Text & "|" & Environment.NewLine
Next
System.IO.File.WriteAllText("C:\output\output.txt", str)
End Sub
Results of output file (output.txt) when button3 is clicked are below:
C:\DirectoryTest\Clients\2356851-Kathy Winkler - Family Investments.pdf|2356851|2356851||04/10/2013|
C:\DirectoryTest\Clients\58736 -Katrina Armon - Sandlewood Homes Co.pdf|58736|58736||04/10/2013|
C:\DirectoryTest\Clients\Karen Cooper - 001548 - Famtime.pdf|Karen Cooper|Karen Cooper||04/10/2013|
My code so far does exactly what I want it to do, the only thing is that I want to make the code smarter but don’t know how. Smarter as in is there a way I can make the below code only pick up the 5 to 10 digit account number seen in the filename, and if no account number exists in the file name to bring up a message box?
System.IO.Path.GetFileNameWithoutExtension(File).Split("-")(0).Trim & "|" & System.IO.Path.GetFileNameWithoutExtension(File).Split("-")(0).Trim
As you can see from the last line of the output…
C:\DirectoryTest\Clients\Karen Cooper - 001548 - Famtime.pdf|Karen Cooper|Karen Cooper||04/10/2013|
…the customers name “Karen Cooper” is being displayed in both areas where the account number should be displayed. This is why I need to make this code smarter somehow have it search the file name for a 5 to 10 digit account number to display it after the file name as see in the other 2 examples.
Please let me know if this is possible. And do let me know if you have any questions.
Here is you some simple logic .... ofcouse you can just do something like finding the filename first but here you go
Dim returnval As String = ""
Dim s As String = "C:\DirectoryTest\Clients\Karen Cooper - 001548 - Famtime.pdf|Karen Cooper|Karen Cooper||04/10/2013|"
For Each p As String In s
If IsNumeric(p) Then
returnval += p
Else
'MsgBox("no")
End If
Next
msgbox(returnval) will hold all your numbers 5-10 , depends on how specific you want to get from here
to break apart the filenames
'This will extract and return the filename from the specified path and filename.
'
Dim filePath As String = "c:\MyDirectory\MYFile.txt"
Dim slashPosition As Integer = filePath.LastIndexOf("\")
Dim filenameOnly As String = filePAth.Substring(slashPosition + 1)
MsgBox(filenameOnly)
*FOUND AT LINK http://www.vbforfree.com/274/extract-and-retrieve-the-filename-from-a-path/*
then manipulate your string from there as much as you want
You should give this a try. I haven't had a chance to test it but it should work
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim str As String
For Each File As String In System.IO.Directory.GetFiles(TextBox1.Text)
Dim strs as String() = System.IO.Path.GetFileNameWithoutExtension(File).Split("-")
Dim AccountNum as int = 0
For each section in strs()
' Loop through each section separated by - and try to cast it to an int
' you may want to use cLong instead
Try
AccountNum = cInt(section.trim())
exit for
Catch
End Try
Next
' DO LOGIC HERE TO BUILD OUTPUT with the account num now known
Next
System.IO.File.WriteAllText("C:\output\output.txt", str)
End Sub
How about yor file name ?
C:\DirectoryTest\Clients\Karen Cooper - 001548 - Famtime.pdf
Fairly, It should be
C:\DirectoryTest\Clients\001548 - Karen Cooper - Famtime.pdf
I would recommend using RegEx to extract the account number. A side benefit of using RegEx is that you can store the RegEx pattern outside of your code, such as in a configuration file, so if you ever need to modify the pattern, you could do so easily without recompiling your application.
Function GetAccountNumber(fileName As String) As String
Dim pattern As String = ".*?(?<acct>\d{5,10}).*?"
Dim regEx As New Regex(pattern)
Dim match As Match = regEx.Match(fileName)
Dim accountNumber As String = Nothing
If match.Success Then
Dim group As Group = match.Groups("acct")
If group.Success Then
accountNumber = group.Value
End If
End If
Return accountNumber
End Function
In the above example, I am using the following RegEx pattern to find the five to ten digit number in the string:
.*?(?<acct>\d{5,10}).*?
The .*? at the beginning and end of the pattern means any character, any number of times. The question mark means it's non-greedy. In other words, it only matches as many characters as necessary. By making it non-greedy, it will not steal-away any of the digits from the account number.
The parentheses surround the part of the string we are looking for (the account number). The ?<acct> at the beginning of the parenthetical group a name by which we can refer to it. In this case, I named the group acct. The \d means any digit character. The {5,10} means repeated between five and ten times.
I'm trying to convert a string that contains someones name as "Last, First" to "First Last".
This is how I am doing it now:
name = name.Trim
name = name.Substring(name.IndexOf(",") + 1, name.Length) & " " & name.Substring(0, name.IndexOf(",") - 1)
When I do this I get the following error:
ArgumentOutOfRangeException was unhandled
Index and length must refer to a location within the string
Parameter name: length
Can someone explain why I am getting this error and how I should be doing this?
You are getting error on this:
name.Substring(name.IndexOf(",") + 1, name.Length)
name.Length should have subtracted with the length of the string before the comma.
The best way for that is to split the string.
Dim oFullname as string = "Last, First"
Dim oStr() as string = oFullname.split(","c)
oFullname = oStr(1).trim & " " & oStr(0).trim
MsgBox (oFullname)
The second parameter for String.Substring is the length of the substring, not the end position. For this reason, you're always going to go out of bounds if you do str.Substring(n, str.Length) with n > 0 (which would be the whole point of a substring).
You need to subtract name.IndexOf(",") + 1 from name.Length in your first substring. Or just split the string, as the others have suggested.
simply ,you only need to split the string
Dim originalName As String = "Last,First"
Dim parts = name.Split(","C)
Dim name As String = parts(1) & " " & parts(0)
If you're using the Unix command line--like the terminal on a Mac--you can do it like this:
Let's say that you have a file containing your last-comma-space-first type names like this:
Last1, First1
Last2, First2
Last3, First3
OK, now let's save it as last_comma_space_first.txt. At this point you can use this command I came up with for your particular problem:
sed -E 's/([A-Za-z0-9]+), ([A-Za-z0-9]+)/\2 \1/g' last_comma_space_first.txt > first_space_last.txt
--->>> Scroll --->>>
You're done! Now, go check that first_space_last.txt file! ^_^ You should get the following:
First1 Last1
First2 Last2
First3 Last3
Tell your friends... Or don't...
This would work keeping to the posters format.
Name = "Doe,John"
Name = Replace(Name.Substring(Name.IndexOf(","), Name.Length - Name.IndexOf(",")) & " " & Name.Substring(0, Name.IndexOf(",")), ",", "")
Result Name = "John Doe"
Please be easy on me guys as I'm still learning.
The following code:
Imports System.Console
Module Module1
Sub Main()
Dim num As Integer
Dim name As String
num = 1
name = "John"
WriteLine("Hello, {0}", num)
WriteLine("Hello, {0}", name)
WriteLine("Hello, {0}", 1)
WriteLine("Hello, {0}", "John")
WriteLine("5 + 5 = {0}", 5 + 5)
WriteLine()
End Sub
End Module
has the same output as this code:
Imports System.Console
Module Module1
Sub Main()
Dim num As Integer
Dim name As String
num = 1
name = "John"
WriteLine("Hello, " & num)
WriteLine("Hello, " & name)
WriteLine("Hello, " & 1)
WriteLine("Hello, " & "John")
WriteLine("5 + 5 = " & 5 + 5)
WriteLine()
End Sub
End Module
Both output:
Hello, 1
Hello, John
Hello, 1
Hello, John
5 + 5 = 10
I looked everywhere and couldn't find the answer.
When to use "{0}, {1}, ... etc"? and when to use "&"?
Which is better? And why?
With {0} you're specifying a format placeholder, whereas with & you're just concatenating the string.
Using format placeholders
Dim name As String = String.Format("{0} {1}", "James", "Johnson")
Using string concatenation
Dim name As String = "James" & " " & "Johnson"
What you're seeing here are two very different expressions that just so happen to evaluate to the same output.
The & operator in VB.Net is the string concatenation operator. It essentially works by converting both the left and right side of the expression to a String and them adding them together. This means all the below operations are roughly equivalent
"Hello " & num
"Hello " & num.ToString()
"Hello " & CStr(num)
The {0} is a feature of the .Net APIs. It represents a position within a string which will later be replaced with a value. The {0} refers to the first value passed to the function, {1} the second and so on. This means that all the below operations are roughly equivalent
Console.WriteLine("Hello {0}!", num)
Console.WriteLine("Hello " & num & "!")
The reason you see the same output is because putting {0} at the end of the string is almost exactly the same as a string concatenation of the 2 values.
Using {N} is called Composite Formatting. One advantage, besides readability, is the fact that you can easily set alignment and format properties. Example from the MSDN link:
Dim MyInt As Integer = 100
Console.WriteLine("{0:C}", MyInt)
' The example displays the following output
' if en-US is the current culture:
' $100.00
{0} is a placeholder that is used in conjunction with String.Format in order to have a more readable and performant string substitutions. Several method calls, including WriteLine, have implicit calls to String.Format.
The problem with using concatenation is that each concat operation will create a new string, which consumes memory.
If you are performing a lot of substitutions, then the best performance will be to use System.Text.StringBuilder instead.