Indent a string by 4 spaces (Add Tab to string) - string

I am trying to add indentation to a string, essentially adding 4 spaces in front of each line in the string. The string that I want to add the indentation to is called StringToIndent.
Public Class ModifyPage
Private Sub Button_Test_Click(sender As Object, e As RoutedEventArgs) Handles Button_Test.Click
Dim StringToIndent As String = ("This is the first row
This is the second row
This is the third and final row in MyString")
Dim MySecondString As String = "This is a string in one line."
Dim BothStringsTogether = StringToIndent & Environment.NewLine & MySecondString
Debug.Write(BothStringsTogether)
End Sub
End Class
The current output:
This is the first row
This is the second row
This is the third and final row in MyString
This is a string in one line.
I want the final code (that is indented) to output:
This is the first row
This is the second row
This is the third and final row in MyString
This is a string in one line.
How can this be achieved through code? Is there a formatting option that allows me to add indentation? A method that doesn't require me to loop through a string and adding four spaces for each line would be preferable.
Edit: A way to achieve the expected output is to replace the new line with a new line and then add the indent. However, there must be a more elegant way of doing it?
Code:
Dim StringToIndent As String = ("This is the first row
This is the second row
This is the third and final row in MyString")
Dim indentAmount = 4
Dim indent = New String(" "c, indentAmount)
StringToIndent = indent & StringToIndent.Replace(Environment.NewLine, Environment.NewLine & indent)
Debug.Write(StringToIndent)

Maybe something like:
Dim res as String
Dim parts As String() = StringToIndent.Split(ControlChars.CrLf.ToCharArray)
For Each part As String In parts
res.Append(" ") & part & vbCrLf
Next

In C# you can mark the String as a verbatim string literal by prefixing the literal with the # symbol.
In VB.NET we don't have this option. Instead, a workaround would be to create an XML literal and get the value. Here is an example:
Dim input As String = <element> This is the first row
This is the second row
This is the third and final row in MyString
This is a string in one line.
</element>.Value().ToString()
Debugger.WriteLine(input.ToString())
If the value is not static, e.g. you're getting it from somewhere, then you're forced to iterate through the String in some form. You can either Replace like in your example, do a Split and Join (similar to your example), or you'll need to manually iterate.
The manual iteration could look more elegant using LINQ, but you don't gain anything from it.
The bottom line is that if your String is static then you can use the XML literal example I provided, otherwise if the String is dynamic then your solution is perfectly appropriate.
UPDATE
As Andrew Morton pointed out, multiple line String literals have existed since Visual Studio 2017. The following would produce the same outcome as my XML literal example:
Dim input As String = " This is the first row
This is the second row
This is a string in one line"
Debugger.WriteLine(input)

Using an interpolated string indicated by the $ preceeding the string and the vb constants.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim s = $"{vbTab}This Is the first row{vbCrLf}{vbTab}This Is the second row{vbCrLf}{vbTab}{vbTab}This Is the third And final row in MyString{vbCrLf}This Is a string in one line."
Debug.Print(s)
End Sub

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

Parsing name/value pairs containing spaces delimited by spaces

I'm trying to parse a file in vb.net. This file is the output of a CLI command on Mikrotik RouterOS.
The file looks like this, where the \ and the end of the line means the line continues below
# jan/03/2017 12:46:35 by RouterOS 6.38
# software id = 3BQ2-2I1I
#
/queue simple
add dst=WAN max-limit=5M/20M name=Compartido01 priority=1/1 queue=\
wireless-default/wireless-default target="" total-priority=1
add max-limit=512k/2M name="6206101450 - Simone Walter (2M) (P13)" parent=\
Compartido01 target=190.211.88.1/32
add max-limit=350k/1M name=\
"6206130537 - Figueroa Viviana del Carmen (1M) (P14)" parent=Compartido01 \
target=190.211.88.24/32
I managed to skip the 4 first lines and collapse them so they look like this
"add dst=WAN max-limit=5M/20M name=Compartido01 priority=1/1 queue=wireless-default/wireless-default target="" total-priority=1"
"add max-limit=512k/2M name="6206101450 - Simone Walter (2M) (P13)" parent=Compartido01 target=190.211.88.1/32"
"add max-limit=350k/1M name="6206130537 - Figueroa Viviana del Carmen (1M) (P14)" parent=Compartido01 target=190.211.88.24/32"
What I need to do is to extract the information on those strings, something like "name=XXXXXX" and "target=XXXXX"
I could split using space as delimiter but the "name" field can have spaces inside it
Anyone can give me a hint ?
What you need is a RegEx match parser...Found one here. See if you can make what you need from this.
Imports System.Text.RegularExpressions
Module Parser
Public Function ParseKeyValuePairs(ByVal Buffer As String) As Dictionary(Of String, String)
Dim Result = New Dictionary(Of String, String)
'---- There are 3 sub patterns contained here, seperated at the | characters
' The first retrieves name="value", honoring doubled inner quotes
' The second retrieves name=value where value can't contain spaces
' The third retrieves name alone, where there is no "=value" part (ie a "flag" key
' where simply its existance has meaning
Dim Pattern = "(?:(?<key>[\w-]+)\s*\=\s*""(?<value>[^""]*(?:""""[^""]*)*)"") | " & _
"(?:(?<key>[\w-]+)\s*\=\s*(?<value>[^""\s]*)) | " & _
"(?:(?<key>[\w-]+)\s*)"
Dim r = New System.Text.RegularExpressions.Regex(Pattern, RegexOptions.IgnorePatternWhitespace)
'---- parse the matches
Dim m As System.Text.RegularExpressions.MatchCollection = r.Matches(Buffer)
'---- break the matches up into Key value pairs in the return dictionary
For Each Match As System.Text.RegularExpressions.Match In m
Result.Add(Match.Groups("key").Value, Match.Groups("value").Value)
Next
Return Result
End Function
Public Sub Main()
Dim s = "Key1=Value Key2=""My Value here"" Key3=Test Key4 Key5"
Dim r = ParseKeyValuePairs(s)
For Each i In r
Debug.Print(i.Key & "=" & i.Value)
Next
End Sub
End Module

Why does Excel treat double spaces as a comma?

I wrote an export to CSV file in my vb.net application, and I then exported it into Outlook.
The issue I've got, is that when the CSV file is being written, my code is checking for a comma in the current field, but while doing this, it also mistakes a double space for a comma, or space followed by 'Enter' key being pressed (for multiline textboxes)
An example would be if in the notes section of the customer, there is 4 lines of text, and one ends in a space - The user has then pressed enter to go to the next line, however the program is taking the next line of text and creating a new record for it, as it thinks it's a comma...
What is the reason for this? This means that data has to be super validated (ie checking for no double spaces etc) before it can be exported, which is far too time consuming.
Hopefully this makes sense!
This is the code:
Dim result As Boolean = True
Try
Dim sb As New StringBuilder()
Dim separator As String = ","
Dim group As String = """"
Dim newLine As String = Environment.NewLine
For Each column As DataColumn In dtable.Columns
sb.Append(wrapValue(column.ColumnName, group, separator) & separator)
Next
sb.Append(newLine)
For Each row As DataRow In dtable.Rows
For Each col As DataColumn In dtable.Columns
sb.Append(wrapValue(row(col).ToString(), group, separator) & separator)
Next
sb.Append(newLine)
Next
The code for wrapValue
Function wrapValue(value As String, group As String, separator As String) As String
If value.Contains(separator) Then
If value.Contains(group) Then
value = value.Replace(group, group + group)
End If
value = group & value & group
End If
Return value
End Function
Based on the fact that it's shortening it by 430 lines, I'd suggest it's something to do with the fact you're adding a load of "" before and after the value variable.
If it's removing a value at the start, then it will be removing a " before the first column header. As to why it's importing one record as you mentioned in the comments, I'm not entirely sure, however, I would suggest the issue lies in your wrapValue code.
Can you try changing
value = group & value & group
to
value = value
and see if that changes anything?

Finding multiple instance of a variable length string in a string

I'm trying to extract my parameters from my SQL query to build my xml for an SSRS report. I want to be able to copy/paste my SQL into Excel, look through the code and find all instances of '#' and the appropriate parameter attached to it. These paramaters will ultimately be copied and pasted to another sheet for further use. So for example:
where DateField between #FromDate and #ToDate
and (BalanceFiled between #BalanceFrom and #BalanceTo
OR BalancdField = #BalanceFrom)
I know I can use Instr to find the starting position of the first '#' in a line but how then do I go about extracting the rest of the parameter name (which varies) and also, in the first two lines of the example, finding the second parameter and extracting it's variable lenght? I've also tried using the .Find method which I've been able to copy the whole line over but not just the parameters.
I might approach this problem like so:
Remove characters that are not surrounded by spaces, but do not
belong. In your example, the parentheses need to be removed.
Split the text using the space as a delimiter.
For each element in the split array, check the first character.
If it is "#", then the parameter is found, and it is the entire value in that part of the array.
My user-defined function looks something like this:
Public Function GetParameters(ByRef rsSQL As String) As String
Dim sWords() As String
Dim s As Variant
Dim sResult As String
'remove parentheses and split at space
sWords = Split(Replace(Replace(rsSQL, ")", ""), "(", ""), " ")
'find parameters
For Each s In sWords
If Left$(s, 1) = "#" Then
sResult = sResult & s & ", "
End If
Next s
'remove extra comma from list
If sResult <> "" Then
sResult = Left$(sResult, Len(sResult) - 2)
End If
GetParameters = sResult
End Function

VB.Net Split A Group Of Text

I am looking to split up multiple lines of text to single them out, for example:
Url/Host:ftp://server.com/1
Login:Admin1
Password:Password1
Url/Host:ftp://server.com/2
Login:Admin2
Password:Password2
Url/Host:ftp://server.com/3
Login:Admin3
Password:Password3
How can I split each section into a different textbox, so that section one would be put into TextBox1.Text on its own:
Url/Host:ftp://server.com/1
Login:Admin1
Password:Password1
If that's the exact format you could just split it on two newlines in a row:
Dim text As String ' your text
Dim sep() As String = {vbNewLine & vbNewLine}
Dim sections() As String = text.Split(sep, StringSplitOptions.None)
and then just loop through them and put one value in each Textbox.

Resources