VB.net Trim function - string

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

Related

Find and string in a string and change it

I have a 2-dimensional array of values looking like that:
In a different table, I have long strings with VALUE_1, VALUE_2 that can be found anywhere. It looks like in the table below:
Now, I want to write a program that translates the existing VALUE_1, VALUE_2 etc. in the long strings by adding the respective element in the 2nd dimension of the array (/BB, /CCC etc.) and if necessary duplicating and separating the values with a comma and a blank space. So VALUE_1 for example is turned into VALUE_1/BB, VALUE_1/A for each finding in the string. The result is supposed to look exactly like in the table below.
That's challenging. I my first approach I tried to locate the VALUE_1, VALUE_2 in the strings by using InStr() but I don't think that this will help me since only the first hit is taken into consideration. I need every occurrence.
For i = 1 To Worksheets("table2").Range("H1").End(xlDown).Row
For j = LBound(arr2) To UBound(arr2)
If InStr(Worksheets("table2").Range("H" & i), arr2(j, 0)) > 0 Then
Worksheets("table2").Range("H" & i).Font.Bold = True
End If
Next j
Next i
Use your 2D table to build a scripting dictionary so that value1 is associated with the concatenation of all column values in column 2 that have value 1 in the first column.
In the (untested) code below the array (ipArray)is that derived from the 2D range.
Public Function GetReplacements(ByVal ipArray As Variant) As Scripting.dictionary
Dim myD As Scripting.dictionary
Set myD = New Scripting.dictionary
Dim myIndex As Long
For myIndex = LBound(ipArray) To UBound(ipArray)
Dim myKey As String
myKey = ipArray(myIndex, 1)
Dim myItem As String
myItem = ipArray(myIndex, 2)
If myD.exists(myKey) Then
myD.Item(myKey) = myD.Item(myKey) & ", " & myKey & myItem
Else
myD.Add myKey, myKey & myItem
End If
Next
Set GetReplacements = myD
End Function
Now when you find an item such as "Value 1" you can replace with the value retrieved from the dictionary.
Building on #freeflow's excellent answer, I would also use a Scripting.Dictionary to hold the mappings from VALUE1 etc. to the target text.
I would then use Replace for each key in the Dictionary. You can loop like:
Dim key as Variant
For Each key in dict
Replace(<your string>, CStr(key), dict(key))
Next key
This will work so long as all your 'find' strings are totally unique i.e. none of them appears within another - so if you had "Value" and "Value 1" it would not work. Also, the simplest form of this method only works if there is a one-to-one mapping of text strings.
Thus, if your sample data is representative, you would want to look into using the Count argument of Replace so that you can replace the second occurrence of VALUE_4 with the different text, and so on.
I would do this by storing the dict values as an array e.g.
Dim my_arr(1 to 3) as String
my_arr(1) = "VALUE_4/CCC"
my_arr(2) = "VALUE_4/DDDD"
my_arr(3) = "VALUE_4/A"
dict.Add "VALUE_4", my_arr
Then when you are looping through, you can keep track of a counter (call it 'i' for example) and then you can just use Replace with a count of 1, increment 'i' by 1, and then use 'i' in each iteration to call on the relevant element of the array stored against VALUE_4 in the dict, like:
For Each key in dict
For i = LBound(dict(key)) to UBound(dict(key))
Replace (<your string>, CStr(key), dict(key)(i), 1, 1)
Next i
Next key
Hopefully you can build from there to what you need? Having reread your original post, I actually think my simplest solution would work (but I'll leave the more complex solution there in case it's of use to you or others), so long as dict is used to store the one-to-one mapping of, for example, "VALUE_1" to "VALUE_1/BB, VALUE_1/A" - you can loop through your original table and build those strings by concatenation - maybe even directly in the dict:
For Each cell in TableCol1 ' assuming it is cells, otherwise use an appropriate form of loop
tmp_str = cell.Value2
If dict.Exists(tmp_str) Then
dict(tmp_str) = dict(tmp_str) + ", " + tmp_str+cell.Offset(0,1).Value2
Else
dict.Add tmp_str, tmp_str + cell.Offset(0,1).Value2
End If
Next cell

regex for Excel to remove all but specific symbols after a specific symbol?

I have stings like this which are addresses, e.g.:
P.O. Box 422, E-commerce park<br>Vredenberg<br><br><br>Curaçao
Adelgatan 21<br>Malmö<br><br>211 22<br>Sweden
Läntinen Pitkäkatu 35 A 15<br>Turku<br><br>20100<br>Finland
I am interested in Country only. Country always comes last after a <br> tag.
Note, that there can be several such tags preceding this last value (e.g. 1st example string).
Is there a good way to do a formula may ve along those lines:
Identify end of string
Loop a character back until one reaches ">" character
Cut everything else (including the ">" encountered)
You don't need RegEx to do this if it's always the last part of the string.
You can get it with String modifiers doing
Sub Test()
Dim str As String, str1 As String, str2 As String
Dim Countries As String
str = "P.O. Box 422, E-commerce park<br>Vredenberg<br><br><br>Curaçao"
str1 = "Adelgatan 21<br>Malmö<br><br>211 22<br>Sweden"
str2 = "La¨ntinen Pitka¨katu 35 A 15<br>Turku<br><br>20100<br>Finland"
Countries = Right(str, Len(str) - InStrRev(str, "<br>") - 3)
Countries = Countries + vbNewLine + Right(str1, Len(str1) - InStrRev(str1, "<br>") - 3)
Countries = Countries + vbNewLine + Right(str2, Len(str2) - InStrRev(str2, "<br>") - 3)
MsgBox Countries
End Sub
Obviously this will need to be updated for how your data set is stored. You can loop through the dataset and use the string modifier on each line
A formula works too. If a string in A1, write in B1:
=TRIM(RIGHT(SUBSTITUTE(A1,"<br>",REPT(" ",100)),100))
Modified using an approach taken from here:
https://exceljet.net/formula/get-last-word

VBA split string into substrings from file directory

I've searched for this topic a lot but haven't found my exact issue. Also I seemingly can't figure out how to adapt the code samples for my use.
I'm trying to split a "file directory string" into substrings from right to left.
"C:\Users\Me\CustomerName\ProductName\2017\"
And split this from right to left, to
year
productname
customername
My attempts at using Split() to get it working, have always split it in the wrong places.
You mentioned you have tried with Split, so this is a good start:
Option Explicit
Public Sub TestMe()
Dim strFolderString As String
Dim arrFolderString As Variant
strFolderString = "C:\Users\Me\CustomerName\ProductName\2017\"
arrFolderString = Split(strFolderString, "\")
Debug.Print arrFolderString(UBound(arrFolderString) - 1)
Debug.Print arrFolderString(UBound(arrFolderString) - 2)
Debug.Print arrFolderString(UBound(arrFolderString) - 3)
End Sub
The idea is to use UBound as the right to left. I do not start from 0, because your string ends with \, thus the 0th position is empty.

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

Resources