I'm a total beginner in the VB language and I have a string in the format:
Smith, Alex (asmith#gmail.com)
I'm attempting to isolate "asmith" from this string. I'm assuming that we would have to split at the "(" and then at the "#" and obtain the 1st index?
Any help is appreciated.
I'm assuming that we would have to split at the "(" and then at the "#" and obtain the 1st index?
Your approach is correct. A literal translation of your algorithm to VB.NET would be:
Dim firstPartOfMailAddress = text.Split("("c)(1).Split("#"c)(0)
Explanation:
"("c is a character literal. Split expects a character, not a string (that would be "(").
Arrays are zero-based in VB.NET and indexed using the (...) operator. Thus, you take the second part (1) of the first split and the first part (0) of the second split.
Notes:
This code does not include any error handling and will fail horribly if the text does not contain the character (.
An alternative would be to extract the value using a regular expression, but if your are new to the language, splitting is a much easier option.
Here is an option for you:
Dim input = "Smith, Alex (asmith#gmail.com)"
Dim output= input.Split("("c, "#"c)(1)
use class :
Imports System.Globalization
Imports System.Text.RegularExpressions
Public Class RegexUtilities
Dim invalid As Boolean = False
Public Function IsValidEmail(strIn As String) As Boolean
invalid = False
If String.IsNullOrEmpty(strIn) Then Return False
' Use IdnMapping class to convert Unicode domain names.
Try
strIn = Regex.Replace(strIn, "(#)(.+)$", AddressOf Me.DomainMapper,
RegexOptions.None, TimeSpan.FromMilliseconds(200))
Catch e As RegexMatchTimeoutException
Return False
End Try
If invalid Then Return False
' Return true if strIn is in valid e-mail format.
Try
Return Regex.IsMatch(strIn,
"^(?("")("".+?(?<!\\)""#)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])#))" +
"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$",
RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250))
Catch e As RegexMatchTimeoutException
Return False
End Try
End Function
Private Function DomainMapper(match As Match) As String
' IdnMapping class with default property values.
Dim idn As New IdnMapping()
Dim domainName As String = match.Groups(2).Value
Try
domainName = idn.GetAscii(domainName)
Catch e As ArgumentException
invalid = True
End Try
Return match.Groups(1).Value + domainName
End Function
End Class
and use code in form and customzition :
Dim util As New RegexUtilities()
Dim emailAddresses() As String = {"david.jones#proseware.com", "d.j#server1.proseware.com",
"jones#ms1.proseware.com", "j.#server1.proseware.com",
"j#proseware.com9", "js#internal#proseware.com",
"j_9#[129.126.118.1]", "j..s#proseware.com",
"js*#proseware.com", "js#proseware..com",
"js#proseware.com9", "j.s#server1.proseware.com",
"""j\""s\""""#proseware.com", "js#contoso.中国"}
For Each emailAddress As String In emailAddresses
If util.IsValidEmail(emailAddress) Then
Console.WriteLine("Valid: {0}", emailAddress)
Else
Console.WriteLine("Invalid: {0}", emailAddress)
End If
Next
Related
What would be the efficient way to read a paragraph, and replace anything between square brackets []? In my case following paragraph,
I agree to [Terms of Use|https://www.google.com/terms-use], [Privacy Statement|https://www.google.com/privacy-statement] and [Misc Term|https://www.google.com/misc-terms]
should parsed as,
I agree to Terms of Use, Privacy Statement and Misc Term
You can use the following regular expression pattern to match the brackets:
\[[^]]+]
This is what the pattern means:
\[ match an open bracket
[^]]+ match anything but a closed bracket one or more times
] match a closed bracket
Here is an example fiddle: https://regex101.com/r/Iyk9kR/1
Once you have the matches, you would:
Use Regex.Replace (documentation)
Use the MatchEvaluator overload
In the MatchEvaluator, use String.Split (documentation) on the pipe character
Dynamically build your anchor tag by setting the href attribute to the second match of the split and the innerHTML to the first match of the split
It might be worth adding some conditional checking in between steps 2 and 3, but I'm not sure of your exact requirements.
Here is an example:
Imports System
Imports System.Text.RegularExpressions
Public Module Module1
Public Sub Main()
Dim literal = "I agree to [Terms of Use|https://www.google.com/terms-use], [Privacy Statement|https://www.google.com/privacy-statement] and [Misc Term|https://www.google.com/misc-terms]"
Dim regexPattern = "\[[^]]+]"
Dim massagedLiteral = Regex.Replace(literal, regexPattern, AddressOf ConvertToAnchor)
Console.WriteLine(massagedLiteral)
End Sub
Private Function ConvertToAnchor(m As Match) As String
Dim matches = m.Value.Split("|"c)
Return "" & matches(0).Substring(1) & ""
End Function
End Module
Fiddle: https://dotnetfiddle.net/xUE8St
Dim rtnStr = "String goes here"
Dim pattern As String = "\[.*?\]"
If Regex.IsMatch(rtnStr, pattern) Then
Dim matches = Regex.Matches(rtnStr, pattern, RegexOptions.IgnoreCase)
For index As Integer = 0 To matches.Count - 1
If matches(index).ToString().Contains("|") Then
Dim splitBracket = matches(index).ToString().Split("|")
Dim linkName = String.Empty
Dim linkUrl = String.Empty
If splitBracket.Length > 0 Then
linkName = splitBracket(0).Replace("[", "")
linkUrl = splitBracket(1).Replace("]", "")
End If
Dim linkHtml = "<a class=""terms"" href=""javascript: void(0);"" data-url=" + linkUrl + ">" + linkName + "</a>"
rtnStr = rtnStr.Replace(matches(index).ToString(), linkHtml)
End If
Next
End If
#Html.Raw(rtnStr)
I would like to ask for your help regarding my problem. I want to create a module for my program where it would read .txt file, find a specific value and insert it to the text box.
As an example I have a text file called system.txt which contains single line text. The text is something like this:
[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]
What i want to do is to get only the last name value "xxx_xxx" which every time can be different and insert it to my form's text box
Im totally new in programming, was looking for the other examples but couldnt find anything what would fit exactly to my situation.
Here is what i could write so far but i dont have any idea if there is any logic in my code:
Dim field As New List(Of String)
Private Sub readcrnFile()
For Each line In File.ReadAllLines(C:\test\test_1\db\update\network\system.txt)
For i = 1 To 3
If line.Contains("Last Name=" & i) Then
field.Add(line.Substring(line.IndexOf("=") + 2))
End If
Next
Next
End Sub
Im
You can get this down to a function with a single line of code:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Return File.ReadLines(fileName).Where(Function(line) RegEx.IsMatch(line, "[[[]Last Name=(?<LastName>[^]]+)]").Select(Function(line) RegEx.Match(line, exp).Groups("LastName").Value)
End Function
But for readability/maintainability and to avoid repeating the expression evaluation on each line I'd spread it out a bit:
Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
Dim exp As New RegEx("[[[]Last Name=(?<LastName>[^]]+)]")
Return File.ReadLines(fileName).
Select(Function(line) exp.Match(line)).
Where(Function(m) m.Success).
Select(Function(m) m.Groups("LastName").Value)
End Function
See a simple example of the expression here:
https://dotnetfiddle.net/gJf3su
Dim strval As String = " [Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim strline() As String = strval.Split(New String() {"[", "]"}, StringSplitOptions.RemoveEmptyEntries) _
.Where(Function(s) Not String.IsNullOrWhiteSpace(s)) _
.ToArray()
Dim lastnameArray() = strline(1).Split("=")
Dim lastname = lastnameArray(1).ToString()
Using your sample data...
I read the file and trim off the first and last bracket symbol. The small c following the the 2 strings tell the compiler that this is a Char. The braces enclosed an array of Char which is what the Trim method expects.
Next we split the file text into an array of strings with the .Split method. We need to use the overload that accepts a String. Although the docs show Split(String, StringSplitOptions), I could only get it to work with a string array with a single element. Split(String(), StringSplitOptions)
Then I looped through the string array called splits, checking for and element that starts with "Last Name=". As soon as we find it we return a substring that starts at position 10 (starts at zero).
If no match is found, an empty string is returned.
Private Function readcrnFile() As String
Dim LineInput = File.ReadAllText("system.txt").Trim({"["c, "]"c})
Dim splits = LineInput.Split({"]["}, StringSplitOptions.None)
For Each s In splits
If s.StartsWith("Last Name=") Then
Return s.Substring(10)
End If
Next
Return ""
End Function
Usage...
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox1.Text = readcrnFile()
End Sub
You can easily split that line in an array of strings using as separators the [ and ] brackets and removing any empty string from the result.
Dim input As String = "[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim parts = input.Split(New Char() {"["c, "]"c}, StringSplitOptions.RemoveEmptyEntries)
At this point you have an array of strings and you can loop over it to find the entry that starts with the last name key, when you find it you can split at the = character and get the second element of the array
For Each p As String In parts
If p.StartsWith("Last Name") Then
Dim data = p.Split("="c)
field.Add(data(1))
Exit For
End If
Next
Of course, if you are sure that the second entry in each line is the Last Name entry then you can remove the loop and go directly for the entry
Dim data = parts(1).Split("="c)
A more sophisticated way to remove the for each loop with a single line is using some of the IEnumerable extensions available in the Linq namespace.
So, for example, the loop above could be replaced with
field.Add((parts.FirstOrDefault(Function(x) x.StartsWith("Last Name"))).Split("="c)(1))
As you can see, it is a lot more obscure and probably not a good way to do it anyway because there is no check on the eventuality that if the Last Name key is missing in the input string
You should first know the difference between ReadAllLines() and ReadLines().
Then, here's an example using only two simple string manipulation functions, String.IndexOf() and String.Substring():
Sub Main(args As String())
Dim entryMarker As String = "[Last Name="
Dim closingMarker As String = "]"
Dim FileName As String = "C:\test\test_1\db\update\network\system.txt"
Dim value As String = readcrnFile(entryMarker, closingMarker, FileName)
If Not IsNothing(value) Then
Console.WriteLine("value = " & value)
Else
Console.WriteLine("Entry not found")
End If
Console.Write("Press Enter to Quit...")
Console.ReadKey()
End Sub
Private Function readcrnFile(ByVal entry As String, ByVal closingMarker As String, ByVal fileName As String) As String
Dim entryIndex As Integer
Dim closingIndex As Integer
For Each line In File.ReadLines(fileName)
entryIndex = line.IndexOf(entry) ' see if the marker is in our line
If entryIndex <> -1 Then
closingIndex = line.IndexOf(closingMarker, entryIndex + entry.Length) ' find first "]" AFTER our entry marker
If closingIndex <> -1 Then
' calculate the starting position and length of the value after the entry marker
Dim startAt As Integer = entryIndex + entry.Length
Dim length As Integer = closingIndex - startAt
Return line.Substring(startAt, length)
End If
End If
Next
Return Nothing
End Function
I have written a function to extract a recieved token from a "xx":"..." format
Public Class HelperFunctions
Public Function ExtractToken(ByVal myToken As String) As String
'Split fields on comma
Dim fields = myToken.Split(":")
'Quote literal
Dim quote = """"c
'Use trim to remove quotes
Dim value = fields(2).Trim(quote)
Return value
End Function
End Class
But instead of initializing the function
Dim hc as New HelperFunctions
hc.ExtractToken(_string)
I want to use it straight forward
HelperFunctions.ExtractToken(_string)
I have not programmed for a while and cannot figure it out as well as come up with the name of this type of functions to find a tutorial.
You need to declare the Function as Shared:
Public Class HelperFunctions
Public Shared Function ExtractToken(ByVal myToken As String) As String
'Split fields on comma
Dim fields = myToken.Split(":")
'Quote literal
Dim quote = """"c
'Use trim to remove quotes
Dim value = fields(2).Trim(quote)
Return value
End Function
End Class
Or as #jmcilhinney said, you can use Module and you don't need to use Shared in the methods inside it (also you can't create an instance of an object from a Module):
Public Module HelperFunctions
Public Function ExtractToken(ByVal myToken As String) As String
'Split fields on comma
Dim fields = myToken.Split(":")
'Quote literal
Dim quote = """"c
'Use trim to remove quotes
Dim value = fields(2).Trim(quote)
Return value
End Function
End Module
I tried to create a unique code for each shop in the form I made. I have two TextBox controls (TBNameStore and TBCodeStore). What I want is that when I write the name of the shop, for example "Brothers in Arm", in TBNameStore, then TBCodeStore should automatically be filled with the text "BIA".
How can I do that?
Well I write a code that can help you with your problem.
Option Strict On
Public Class Form1
Public Function GetInitials(ByVal MyText As String) As String
Dim Initials As String = ""
Dim AllWords() As String = MyText.Split(" "c)
For Each Word As String In AllWords
If Word.Length > 0 Then
Initials = Initials & Word.Chars(0).ToString.ToUpper
End If
Next
Return Initials
End Function
Private Sub TBNameStore_TextChanged(sender As Object, e As EventArgs) Handles TBNameStore.TextChanged
TBCodeStore.Text = GetInitials(TBNameStore.Text)
End Sub
End Class
Like you can see, the GetInitials get you all the first letter of all the words in the text.
One possible solution using the mentioned Split and SubString methods and LINQ could look like this:
create a StringBuilder where every first character of each word is stored
separate the words using the specified delimiter (default is empty space) using the String.Split method
convert the array to list in order to apply the LINQ-ToList extension => ToList()
for each found word => ForEach(sub (word as String) ...
take the first character from the word, convert it to upper case and put it in the result
=> result.Append(word.SubString(0, 1).ToUpper())
return the result as string => result.ToString()
The code looks like this:
private function abbreviation(input as String, optional delimiter as String = " ")
dim result = new StringBuilder()
input.Split(delimiter) _
.ToList() _
.ForEach(sub (word as String)
result.Append(word.SubString(0, 1).ToUpper())
end sub)
return result.ToString()
end function
Usage:
dim s = "Brothers in Arms"
Console.WriteLine("{0} => {1}", s, abbreviation(s))
and the output looks like expected:
Brothers in Arms => BIA
We perform a protocol based data sending to device where the device requires a formatted data packets.
the sample packet data is XXFSXXXFSXXXXXXXFSXXXXXX. The X mentioned is the max length size of each string. if data is less than string max length it should be filled with NULL character like ..11FS123FS1234XXXX (the remaining X will be filled with NULL).
I am just trying to convert one of VB6 function to VB.Net and below is the converted statement where i am facing issue
Option Strict Off
Option Explicit On
Imports Microsoft.VisualBasic.Compatibility.VB6
Imports System
Imports System.Runtime.InteropServices
Module FunctionCmd_Msg
Public FunCommand_Msg As Fun_CommandMessage = Fun_CommandMessage.CreateInstance()
'Function Command Message
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ _
Public Structure Fun_CommandMessage
<VBFixedString(1)> Public one As String
<VBFixedString(1)> Public two As String
<VBFixedString(3)> Public three As String
Dim five As String
<VBFixedString(8)> Public four As String
Public Shared Function CreateInstance() As Fun_CommandMessage
Dim result As New Fun_CommandMessage
result.one = String.Empty
result.two = String.Empty
result.three = String.Empty
result.four = String.Empty
result.five = String.Empty
End Function
End Structure
End Module
assuming:
one = "1"
two = "1"
three = "123"
four = "5678"
five = "testing"
FS = character (field separator)
on concatenating the strings i need a fixed length string such like this:
one & two & FS & three & FS & five & FS & four
output: since four is a fixed length string of 8 length remaining 4 characters should be filled with null as below
11 FS 123 FS testing FS 5678XXXX
Fixed-length strings simply make no sense in .NET any more. Microsoft tried to provide a similar class for easier upgrade but the truth is that you should change your code depending on usage:
What did the fixed-length string do in your VB6 code? Was it for no good reason? Then use a normal String in .NET.
Was it for interop with a C API? Then use marshalling to set a size for an array in the C API call.
Just forget about the fixed length, and use regular vb.net strings. They will return fine to whatever calls that code, including interop.
So, just pad your strings, and you off to the races.
In fact, build a Msg class that does the dirty work for you.
This looks quite nice to me:
NOTE how I set this up that you ONLY define the length of the string in ONE place. (so I use len(m_string) to determine the length from THEN on in the code.
Also, for debug and this example, in place of vbcharNull (which you should use), I used X for testing.
Now, in your code?
Just use this:
Dim Msg As New MyMsg
With Msg
.one = "A"
.two = "B"
.three = "C"
.four = "D"
.Five = "E"
End With
Debug.WriteLine(Msg.Msg("*") & vbCrLf)
Debug.WriteLine("total lenght = " & Len(Msg.Msg("X").ToString))
Output:
A*B*CXX*EXXXXXXX*DXXXXXXX
total lenght = 25
I note in your code that you have FIVE before FOUR - but if that is what you want, then no problem
Note that the class ALWAYS maintains the lengths for you.
So just paste this code into your module or even a new separate class.
Public Class MyMsg
'Dim cPad As Char = vbNullChar
Dim cPad As Char = "X"
Private m_one As String = New String(cPad, 1)
Private m_two As String = New String(cPad, 1)
Private m_three As String = New String(cPad, 3)
Private m_four As String = New String(cPad, 8)
Private m_five As String = New String(cPad, 8)
Public Property one As String
Get
Return m_one
End Get
Set(value As String)
m_one = MyPad(value, m_one)
End Set
End Property
Public Property two As String
Get
Return m_two
End Get
Set(value As String)
m_two = MyPad(value, m_two)
End Set
End Property
Public Property three As String
Get
Return m_three
End Get
Set(value As String)
m_three = MyPad(value, m_three)
End Set
End Property
Public Property four As String
Get
Return m_four
End Get
Set(value As String)
m_four = MyPad(value, m_four)
End Set
End Property
Public Property Five As String
Get
Return m_five
End Get
Set(value As String)
m_five = MyPad(value, m_five)
End Set
End Property
Public Function Msg(FS As String) As String
Return m_one & FS & m_two & FS & m_three & FS & m_five & FS & m_four
End Function
Private Function MyPad(str As String, strV As String) As String
Return Strings.Left(str & New String(Me.cPad, Len(strV)), Len(strV))
End Function
End Class
As noted, change the commented out line of "X" for the char back to vbCharNull.
And of course you STILL get to choose the delimiter. I used
Msg.Msg("*")
so I used a "*", but you can use space, or anything you want.