VB: Add a space after a specific character into a string if it does not already have one - vb.net

I want all of my strings to be formatted consistently. It is grabbing values from the database and sometimes there are not spaces after colons, but there should be. My goal is to add a space after a colon (:) if there isn't one already. I would prefer to do this without regex, but I am open to any solutions! Thanks so much.

Edit: Apologies I read the title as VBA, have updated now.
Here is a nice simple solution for you.
Replace everything with a Colon and a space with just a Colon meaning all Colons no longer have a space regardless of weather they did or not initially.
Then Replace all Colons with a Colon and a Space:
Dim value1 As String = "Hello:World"
value1 = value1.Replace(": ", ":").Replace(":", ": ")

I can't say it's the most elegant. And its performance is not optimized, though using String.IndexOf should in general be faster than looping over every character. But being a brute force solution, it sure doesn't use regex. ;)
Besides regex, I'm sure there's a cute one-line solution using LINQ, but it's probably hard to read and maintain. Someone is welcome to post that for comparison.
Option Strict On
Module Module1
Sub Main()
Console.WriteLine(EnsureSpaceAfterColon("first: second:asdf third::"))
'prints:
'"first: second: asdf third: : "
End Sub
Public Function EnsureSpaceAfterColon(input As String) As String
Dim colon As Char = CChar(":")
Dim space As Char = CChar(" ")
Dim returnString As String = String.Copy(input) 'leave the original alone
Dim index As Integer = input.IndexOf(colon)
While index > -1 'String.IndexOf returns -1 if the index is not found
'if the index is the last index, there is no space, so add it
'or else if the Char at the next index is not a space, make it so
If index = returnString.Length - 1 OrElse returnString.Chars(index + 1) <> space Then
returnString = returnString.Insert(index + 1, space)
End If
'get the next index
index = returnString.IndexOf(colon, index + 1)
End While
Return returnString
End Function
End Module

Public Module Module1
Public Sub Main()
dim nospace as string = EnsureSpace("xxx:")
dim space as string = EnsureSpace("xxx: ")
Console.WriteLine("|" + nospace + "|")
Console.WriteLine("|" + space + "|")
End Sub
private function EnsureSpace(val as string)
dim temp as string = val.trim
return temp.padright(temp.length + 1)
end function
' OR
private function EnsureSpace1(val as string)
return val.substring(0, val.LastIndexOf(":") + 1) + " "
end function
End Module
|xxx: |
|xxx: |

Three different approaches (all different from the other answers)...pick your poison:
(1) Using a helper Iterator function and String.Join():
Public Function AddSpaceAfterColons(ByVal input As String) As String
Return String.Join("", ColonHelper(input))
End Function
Public Iterator Function ColonHelper(ByVal input As String) As IEnumerable(Of Char)
Dim lastCh As Nullable(Of Char)
For Each ch As Char In input
If lastCh.HasValue AndAlso lastCh.Value = ":"c AndAlso Not (ch = " "c) Then
Yield " "c
End If
Yield ch
lastCh = ch
Next
If lastCh.HasValue AndAlso lastCh.Value = ":"c Then
Yield " "c
End If
End Function
(2) Walking backwards through a StringBuilder:
Public Function AddSpaceAfterColons(ByVal input As String) As String
Static colon As Char = ":"c
Static space As Char = " "c
Dim sb As New System.Text.StringBuilder(input)
For i As Integer = sb.Length - 1 To 0 Step -1
If sb(i) = colon Then
If i = (sb.Length - 1) OrElse sb(i + 1) = space Then
sb.Insert(i + 1, space)
End If
End If
Next
Return sb.ToString
End Function
(3) Using String.Split() and a StringBuilder:
Public Function AddSpaceAfterColons(ByVal input As String) As String
Dim sb As New System.Text.StringBuilder
Dim parts() As String = input.Split(":")
sb.Append(parts(0))
For i As Integer = 1 To parts.Length - 1
sb.Append(":")
If Not parts(i).StartsWith(" ") Then
sb.Append(" ")
End If
sb.Append(parts(i))
Next
Return sb.ToString
End Function

Related

Is there a function to get string between 2 string in vb.net

In a failed attempt to teach my daughter programming I taught her to make this
Public Shared Function getBetween(strSource As String, startSearchIndex As Integer, startSearch As String, endSearch As String) As (nextIndex As Integer, Content As String)
Dim IndexStart = strSource.IndexOf(startSearch, startSearchIndex)
Dim startContent = IndexStart + startSearch.Length
Dim indexEnd = strSource.IndexOf(endSearch, startContent)
Dim content = strSource.Substring(startContent, indexEnd - startContent)
Dim nextIndex = indexEnd + endSearch.Length
Return (nextIndex, content)
End Function
We know what the function does. Get strings between 2 strings in a big string.
I wonder if there is a built in function for this?
Samples:
If I use this test function
Public Shared Sub test(txt As TextBox)
Dim source = "0123456789([012345])0123456789([ABCDEF])0123456789([GHIJK])"
txt.Text += source + System.Environment.NewLine
getBetween3Times(txt, source, "(", ")")
getBetween3Times(txt, source, "([", "])")
getBetween3Times(txt, source, "[", "]")
End Sub
Private Shared Sub getBetween3Times(txt As TextBox, source As String, startsearch As String, endsearch As String)
Dim result = getBetween(source, 0, startsearch, endsearch)
txt.Text += result.Content + System.Environment.NewLine
result = getBetween(source, result.nextIndex, startsearch, endsearch)
txt.Text += result.Content + System.Environment.NewLine
result = getBetween(source, result.nextIndex, startsearch, endsearch)
txt.Text += result.Content + System.Environment.NewLine
End Sub
It will produce
0123456789([012345])0123456789([ABCDEF])0123456789([GHIJK])
[012345]
[ABCDEF]
[GHIJK]
012345
ABCDEF
GHIJK
012345
ABCDEF
GHIJK
No, there is no built-in method, or yes, there are, but you use them already.
Maybe you want to handle invalid input. Also, your method includes the search-token, but you want the text between, so maybe this one is little bit better:
Public Shared Function GetTextBetween(strSource As String, startSearchIndex As Integer, startSearch As String, endSearch As String) As (nextIndex As Integer, Content As String)
If startSearchIndex < 0 Orelse startSearchIndex >= strSource.Length Then Throw New ArgumentException(Nameof(startSearchIndex))
Dim index = strSource.IndexOf(startSearch, startSearchIndex)
If index = -1 Then Return (-1, Nothing)
index += startSearch.Length
Dim endIndex = strSource.IndexOf(endSearch, index+1)
If endIndex = -1 Then Return (-1, Nothing)
Dim content = strSource.Substring(index, endIndex - index)
Return (endIndex + endSearch.Length, content)
End Function
Dim sampleText = "It is the end of the world"
Dim result = GetTextBetween(sampleText, 0, "is ", " of") ' should be "the end"

How to indentify the positions that a word occurs in a given text?

I am developing a program where you can input a sentence and then search for a word. The program will then tell you at which positions this word occurs. I have written some code but do not know how to continue.
Module Module1
Sub Main()
Dim Sentence As String
Dim SentenceLength As Integer
Dim L As Integer = 0
Dim LotsofText As String = Console.ReadLine
Console.WriteLine("Enter your word ") : Sentence = Console.ReadLine
For L = 1 To LotsofText.Length
If (Mid(LotsofText, L, 1)) = " " Then
End If
L = L + 1
Dim TextCounter As Integer = 0
Dim MainWord As String = Sentence
Dim CountChar As String = " "
Do While InStr(MainWord, CountChar) > 0
MainWord = Mid(MainWord, 1 + InStr(MainWord, CountChar), Len(MainWord))
TextCounter = TextCounter + 1
'Text = TextCounter + 2
' Console.WriteLine(Text)
Loop
Console.WriteLine(TextCounter)
Console.Write("Press Enter to Exit")
Console.ReadLine()
End Sub
End Module
Transform this piece of code from C# to Visual Basic. match.Index will indicate the position of the given word.
var rx = new Regex("your");
foreach (Match match in rx.Matches("This is your text! This is your text!"))
{
int i = match.Index;
}
To find only words and not sub-strings (for example to ignore "cat" in "catty"):
Dim LotsofText = "catty cat"
Dim Sentence = "cat"
Dim pattern = "\b" & Regex.Escape(Sentence) & "\b"
Dim matches = Regex.Matches(LotsofText, pattern)
For Each m As Match In matches
Debug.Print(m.Index & "") ' 6
Next
If you want to find sub-strings too, you can remove the "\b" parts.
If you add this function to your code:
Public Function GetIndexes(ByVal SearchWithinThis As String, ByVal SearchForThis As String) As List(Of Integer)
Dim Result As New List(Of Integer)
Dim i As Integer = SearchWithinThis.IndexOf(SearchForThis)
While (i <> -1)
Result.Add(i)
i = SearchWithinThis.IndexOf(SearchForThis, i + 1)
End While
Return Result
End Function
And call the function in your code:
Dim Indexes as list(of Integer) = GetIndexes(LotsofText, Sentence)
Now GetIndexes will find all indexes of the word you are searching for within the sentence and put them in the list Indexes.

manipulate StringBuilder in vb.net

I have a Note as stringBuilder with word and date: reval 41/50/50
I want to manipulate it, so I will have: reval 05/05/14.
(The date is only when I have the word reval before)
My function is:
Sub correctDateShowing(ByRef Note As StringBuilder)
Dim index, i, j As Integer
For index = 0 To Note.Length - 2
If (Note(index).ToString = "r" And Note(index + 1).ToString = "e") Then
For i = 6 To Note.Length - 1 'start from 6,because I want only the date to be reversed
'Here I am Stuck!!
Next
End If
Next
End Sub
I try to do some replacing with a tmp variable but it didn't work.
I will be glad to get some help.
Thanks All!!!
Sub CorrectDateShowing(ByRef Note As StringBuilder)
Dim str As String = Note.ToString()
Dim arr As String() = str.Split(" "c)
arr(1) = StrReverse(arr(1))
Note = New StringBuilder(arr(0) & " " & arr(1))
End Sub
Split the text into two parts, reverse the second part (the date) and then reconnect them.
Try this:
Dim tempCharArray As char[]
Dim dateStartIndex, dateLength As int
'' Here you need to calculate the date start index and date length (i guess the date length is always 8)
Note.CopyTo(dateStartIndex, tempCharArray, 0, dateLength)
Note.Replace(new String(tempCharArray), new String(Array.Reverse(tempCharArray)), dateStartIndex, dateLength)

Strip all characters in textbox except letters and spaces

I am trying to strip all characters except letters and spaces but i am unable to do so. The code i currently have is below, how could i change that so it does allow spaces? At the moment it takes the text, strips it and it all becomes one big line of text.
Dim InputTxt As String = InputText.Text
Dim OutputTxt As System.Text.StringBuilder = New System.Text.StringBuilder()
For Each Ch As Char In InputTxt
If (Not Char.IsLetter(Ch)) Then
OutputTxt.Append(Ch)
Continue For
End If
Dim CheckIndex As Integer = Asc("a") - (Char.IsUpper(Ch) * -32)
Dim Index As Integer = ((Asc(Ch) - CheckIndex) + 13) Mod 26
OutputTxt.Append(Chr(Index + CheckIndex))
Next
OutputText.Text = (OutputTxt.ToString())
Dim output = New StringBuilder()
For Each ch As Char In InputTxt
If Char.IsLetter(ch) OrElse ch = " " Then
output.Append(ch)
End If
Next
OutputText.Text = output.ToString()
Not fully tested but a simple Regex should sustitute all of your code
Dim s = "ADB,12.#,,,122abC"
Dim result = Regex.Replace(s, "[^a-zA-Z ]+", "")
Console.WriteLine(result)
--> output = ADBabC
Here you can find the Regular Expression Pattern Reference
And here is a way to use LINQ to query the string.
Dim candidateText = "This is a test. Does it work with 123 and !"
Dim q = From c In candidateText
Where Char.IsLetter(c) OrElse c=" "
Select c
candidateText = String.Join("", q.ToArray)
Edit
Removed the Char.IsWhiteSpace in query to match the OP question.
I think graumanoz solution is best and doesn't use any unnecessary operations like ToList, but just for kicks:
Shared Function Strip(ByVal input As String)
Dim output = New StringBuilder()
input.ToList().Where(Function(x) Char.IsLetter(x) OrElse x = " ").ToList().
ForEach(Function(x) output.Append(x))
Return output.ToString()
End Function

Splitting a string based on a set length of characters

MVC 3. Vb.net. Part of my app generates PDF files using Itextsharp. Some strings are too long to go onto the background image correctly. So I basically need to split this string when its over 26 characters long and when it splits it cant split in the middle of a word. from there I will use newline to add the string to the right to the next line... Any ideas that might point me in the right direction.. I did start bulding the function that I will pass the string into test for length and then pass back the string after it finishes but I am stummped after that..
Private Function stringLength(ByVal _string As String) As String
If _string.Length < 26 Then
_string.Split(
End If
End Function
I'm sure there's a million different ways to do this.
You basically need to get all of your words split by the space into a list. After that, you just need to keep checking if the current word plus a space plus the next word reach your threshold or not, and if it does, you move to the next line. Once you have all of your lines, then you rejoin the list into a single string again.
Private Function LimitWidth(ByVal text As String, ByVal maxCharacters As Integer) As String
Dim words As List(Of String) = text.Split(" "c).ToList()
If text.Length < maxCharacters OrElse words.Count = 1 Then
Return text
Else
Dim lines As New List(Of String)
Dim currentLine As String = words(0)
For i As Integer = 1 To words.Count - 1
If (currentLine & " " & words(i)).Length > maxCharacters Then
lines.Add(currentLine)
currentLine = words(i)
If i = words.Count - 1 Then
lines.Add(currentLine)
End If
Else
If i = words.Count - 1 Then
lines.Add(currentLine & " " & words(i))
End If
currentLine &= " " & words(i)
End If
Next
Return String.Join(Environment.NewLine, lines.ToArray())
End If
End Function
To Test:
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
MessageBox.Show(LimitWidth("This is a really long sentence " & _
"meant to demonstrate how to split " & _
"the words into a confined character length.", 26))
End Sub
It sounds like you are asking for a word wrap function.
Since I feel that it's better to answer in a way that promotes learning than to just give answers, I have for you a link that walks you through the process of using Test Driven Development (TDD) to solve this problem. It just so happens that the word wrap problem is a popular coding kata, and Robert C. Martin wrote a somewhat silly fictional story about a developer being taught how to use TDD to solve the word wrap kata.
The code examples are in Java, but it should be trivial to read and translate.
http://thecleancoder.blogspot.com/2010/10/craftsman-62-dark-path.html
The goofy bits are skip-able. Just jump down to the sentences right before the first code snippet.
I would add to it handling of multiline input text with following:
Private Function LimitWidth(ByVal text As String, ByVal maxCharacters As Integer, SplitSign As String) As String
Dim Output As String = ""
Dim OrgLines As List(Of String) = text.Split(Environment.NewLine).ToList()
For x As Integer = 1 To OrgLines.Count - 1
Dim words As List(Of String) = OrgLines(x).Split(" "c).ToList()
If text.Length < maxCharacters OrElse words.Count = 1 Then
Output += OrgLines(x)
Else
Dim lines As New List(Of String)
Dim currentLine As String = words(0)
For i As Integer = 1 To words.Count - 1
If (currentLine & " " & words(i)).Length > maxCharacters Then
lines.Add(currentLine)
currentLine = words(i)
If i = words.Count - 1 Then
lines.Add(currentLine)
End If
Else
If i = words.Count - 1 Then
lines.Add(currentLine & " " & words(i))
End If
currentLine &= " " & words(i)
End If
Next
Output += String.Join(SplitSign, lines.ToArray())
End If
Next
Return Output
End Function
use:
LimitWidth("your text", 80, Environment.NewLine)