Related
I have as input the string in the below format
"[1_5,3,7,1],[1_2,4,1,9],[],[1_1,,4,,,9,2]"
What I need to obtain is the same string but with the number after the _ sorted:
"[1_1,3,5,7],[1_1,2,4,9],[],[1_1,2,4,9,,,]"
Dim tmprequestedArea_selectionAreaIn As String = "[1_5,3,7,1],[1_2,4,1,9],[],[1_1,,4,,,9,2]"
tmprequestedArea_selectionAreaIn = Regex.Replace(requestedArea_selectionAreaIn,"\],\[","#")
tmprequestedArea_selectionAreaIn = Regex.Replace(tmprequestedArea_selectionAreaIn,"\[|\]","")
bracList.AddRange(tmprequestedArea_selectionAreaIn.Split(New Char() {"#"c}, StringSplitOptions.None ))
If sortNumber Then
'Split braclist by _ and puts the value in strList
'If after _ is only one number put only that number, else split it by char "," and put in strList the join of the split by , array
'Sort the array
'in previous example strList will contain a,b,c in position 0 and _d_f (instead of f,d) in position 1
For i As Integer = 0 To bracList.Count -1
Dim tmp As String()
Dim tmpInt As New System.Collections.Generic.List(Of Integer)
If Not(String.IsNullOrEmpty(bracList(i))) Then
Dim tmpRequested As String = bracList(i).Split(New Char() {"_"c})(0)
Dim tmpSelection As String = bracList(i).Split(New Char() {"_"c})(1)
If tmpSelection.Contains(",") Then
tmp = tmpSelection.Split(New Char() {","c})
For j As Integer = 0 To tmp.Length -1
tmpInt.Add(Convert.toInt32(tmp(j)))
Next
tmpInt.Sort
strList.Add("[" + tmpRequested + "_" + String.Join(",",tmpInt ) + "]")
Else
strList.Add("[" + tmpRequested + "_" + tmpSelection + "]" )
End If
Else
strList.Add("[]")
End If
Next i
I'm looking for a better way to manage it.
Try this, as a possible substitute for what you're doing now.
Given this input string:
Dim input As String = "[1_5,3,7,1],[1_2,4,1,9],[],[1_1,,4,,,9,2]"
Note: this will also deal with decimal values without changes. E.g.,
"[1_5.5,3.5,7,1],[1_2.564,4,2.563,9],[],[1_1,,4.23,,,9.0,2.45]"
You can extract the content of the brackets with this pattern: \[(.*?)\] and use Regex.Matches to return a MatchCollection of all the substrings that match the pattern.
Then use a StringBuilder as a container to rebuild the string while the parts are being treated.
Imports System.Linq
Imports System.Text.RegularExpressions
Dim pattern As String = "\[(.*?)\]"
Dim matches = Regex.Matches(input, pattern, RegexOptions.Singleline)
Dim sb As New StringBuilder()
For Each match As Match In matches
Dim value As String = match.Groups(1).Value
If String.IsNullOrEmpty(value) Then
sb.Append("[],")
Continue For
End If
Dim sepPosition As Integer = value.IndexOf("_"c) + 1
sb.Append("[" & value.Substring(0, sepPosition))
Dim values = value.Substring(sepPosition).Split(","c)
sb.Append(String.Join(",", values.Where(Function(n) n.Length > 0).OrderBy(Function(n) CDec(n))))
sb.Append(","c, values.Count(Function(n) n.Length = 0))
sb.Append("],")
Next
Dim result As String = sb.ToString().TrimEnd(","c)
If you don't know about LINQ, this is what it's doing:
String.Join(",", values.Where(Function(n) n.Length > 0).OrderBy(Function(n) CDec(n)))
values is an array of strings, generated by String.Split().
values.Where(Function(n) n.Length > 0): creates an Enumerable(Of String) from values Where the content, n, is a string of length > 0.
I could have written values.Where(Function(n) Not String.IsNUllOrEmpty(n)).
.OrderBy(Function(n) CDec(n))): Orders the resulting Enumerable(Of String) using the string value converted to Decimal and generates an Enumerable(Of String), which is passed back to String.Join(), to rebuild the string, adding a char (","c) between the parts.
values.Count(Function(n) n.Length = 0): Counts the elements of values that have Length = 0 (empty strings). This is the number of empty elements that are represented by a comma, appended at the end of the partial string.
If you are looking for a "way"
I think it is easier to fetch each char of the string and if it is a number you put it in array (and when the char is ']' you start new array) the sort the arrays and replace each number from the string with it's sorted number (so you will just do allocation without the need to reconstruct with regular expression
I wish that I had Visual Studio to provide you the code (it is joyful to code a riddle) ^_^
ps:for the commas you can use a counter for each blank commas an the put it in the end
I have a string (for example: "Hello there. My name is John. I work very hard. Hello there!") and I am trying to find the number of occurrences of the string "hello there". So far, this is the code I have:
Dim input as String = "Hello there. My name is John. I work very hard. Hello there!"
Dim phrase as String = "hello there"
Dim Occurrences As Integer = 0
If input.toLower.Contains(phrase) = True Then
Occurrences = input.Split(phrase).Length
'REM: Do stuff
End If
Unfortunately, what this line of code seems to do is split the string every time it sees the first letter of phrase, in this case, h. So instead of the result Occurrences = 2 that I would hope for, I actually get a much larger number. I know that counting the number of splits in a string is a horrible way to go about doing this, even if I did get the correct answer, so could someone please help me out and provide some assistance?
Yet another idea:
Dim input As String = "Hello there. My name is John. I work very hard. Hello there!"
Dim phrase As String = "Hello there"
Dim Occurrences As Integer = (input.Length - input.Replace(phrase, String.Empty).Length) / phrase.Length
You just need to make sure that phrase.Length > 0.
the best way to do it is this:
Public Function countString(ByVal inputString As String, ByVal stringToBeSearchedInsideTheInputString as String) As Integer
Return System.Text.RegularExpressions.Regex.Split(inputString, stringToBeSearchedInsideTheInputString).Length -1
End Function
str="Thisissumlivinginsumgjhvgsum in the sum bcoz sum ot ih sum"
b= LCase(str)
array1=Split(b,"sum")
l=Ubound(array1)
msgbox l
the output gives u the no. of occurences of a string within another one.
You can create a Do Until loop that stops once an integer variable equals the length of the string you're checking. If the phrase exists, increment your occurences and add the length of the phrase plus the position in which it is found to the cursor variable. If the phrase can not be found, you are done searching (no more results), so set it to the length of the target string. To not count the same occurance more than once, check only from the cursor to the length of the target string in the Loop (strCheckThisString).
Dim input As String = "hello there. this is a test. hello there hello there!"
Dim phrase As String = "hello there"
Dim Occurrences As Integer = 0
Dim intCursor As Integer = 0
Do Until intCursor >= input.Length
Dim strCheckThisString As String = Mid(LCase(input), intCursor + 1, (Len(input) - intCursor))
Dim intPlaceOfPhrase As Integer = InStr(strCheckThisString, phrase)
If intPlaceOfPhrase > 0 Then
Occurrences += 1
intCursor += (intPlaceOfPhrase + Len(phrase) - 1)
Else
intCursor = input.Length
End If
Loop
You just have to change the input of the split function into a string array and then delare the StringSplitOptions.
Try out this line of code:
Occurrences = input.Split({phrase}, StringSplitOptions.None).Length
I haven't checked this, but I'm thinking you'll also have to account for the fact that occurrences would be too high due to the fact that you're splitting using your string and not actually counting how many times it is in the string, so I think Occurrences = Occurrences - 1
Hope this helps
You could create a recursive function using IndexOf. Passing the string to be searched and the string to locate, each recursion increments a Counter and sets the StartIndex to +1 the last found index, until the search string is no longer found. Function will require optional parameters Starting Position and Counter passed by reference:
Function InStrCount(ByVal SourceString As String, _
ByVal SearchString As String, _
Optional ByRef StartPos As Integer = 0, _
Optional ByRef Count As Integer = 0) As Integer
If SourceString.IndexOf(SearchString, StartPos) > -1 Then
Count += 1
InStrCount(SourceString, _
SearchString, _
SourceString.IndexOf(SearchString, StartPos) + 1, _
Count)
End If
Return Count
End Function
Call function by passing string to search and string to locate and, optionally, start position:
Dim input As String = "Hello there. My name is John. I work very hard. Hello there!"
Dim phrase As String = "hello there"
Dim Occurrences As Integer
Occurrances = InStrCount(input.ToLower, phrase.ToLower)
Note the use of .ToLower, which is used to ignore case in your comparison. Do not include this directive if you do wish comparison to be case specific.
One more solution based on InStr(i, str, substr) function (searching substr in str starting from i position, more info about InStr()):
Function findOccurancesCount(baseString, subString)
occurancesCount = 0
i = 1
Do
foundPosition = InStr(i, baseString, subString) 'searching from i position
If foundPosition > 0 Then 'substring is found at foundPosition index
occurancesCount = occurancesCount + 1 'count this occurance
i = foundPosition + 1 'searching from i+1 on the next cycle
End If
Loop While foundPosition <> 0
findOccurancesCount = occurancesCount
End Function
As soon as there is no substring found (InStr returns 0, instead of found substring position in base string), searching is over and occurances count is returned.
Looking at your original attempt, I have found that this should do the trick as "Split" creates an array.
Occurrences = input.split(phrase).ubound
This is CaSe sensitive, so in your case the phrase should equal "Hello there", as there is no "hello there" in the input
Expanding on Sumit Kumar's simple solution, here it is as a one-line working function:
Public Function fnStrCnt(ByVal str As String, ByVal substr As String) As Integer
fnStrCnt = UBound(Split(LCase(str), substr))
End Function
Demo:
Sub testit()
Dim thePhrase
thePhrase = "Once upon a midnight dreary while a man was in a house in the usa."
If fnStrCnt(thePhrase, " a ") > 1 Then
MsgBox "Found " & fnStrCnt(thePhrase, " a ") & " occurrences."
End If
End Sub 'testit()
I don't know if this is more obvious?
Starting from the beginning of longString check the next characters up to the number characters in phrase, if phrase is not found start looking from the second character etc. If it is found start agin from the current position plus the number of characters in phrase and increment the value of occurences
Module Module1
Sub Main()
Dim longString As String = "Hello there. My name is John. I work very hard. Hello there! Hello therehello there"
Dim phrase As String = "hello There"
Dim occurences As Integer = 0
Dim n As Integer = 0
Do Until n >= longString.Length - (phrase.Length - 1)
If longString.ToLower.Substring(n, phrase.Length).Contains(phrase.ToLower) Then
occurences += 1
n = n + (phrase.Length - 1)
End If
n += 1
Loop
Console.WriteLine(occurences)
End Sub
End Module
I used this in Vbscript, You can convert the same to VB.net as well
Dim str, strToFind
str = "sdfsdf:sdsdgs::"
strToFind = ":"
MsgBox GetNoOfOccurranceOf( strToFind, str)
Function GetNoOfOccurranceOf(ByVal subStringToFind As String, ByVal strReference As String)
Dim iTotalLength, newString, iTotalOccCount
iTotalLength = Len(strReference)
newString = Replace(strReference, subStringToFind, "")
iTotalOccCount = iTotalLength - Len(newString)
GetNoOfOccurranceOf = iTotalOccCount
End Function
I know this thread is really old, but I got another solution too:
Function countOccurencesOf(needle As String, s As String)
Dim count As Integer = 0
For i As Integer = 0 to s.Length - 1
If s.Substring(i).Startswith(needle) Then
count = count + 1
End If
Next
Return count
End Function
wordString --> Word for fill in the blank.
key-->Character is replaced.
I have also have the position of the key in keyPos which is calculated randomly
I'm making a fill in the blanks game. Here I need to create blanks at random position. I'm using Replace(wordString, key, "_", , 1)
But this only replace the first occurrence. If my wordString has repeating letters like APPLE it will always replace the first P
I want to replace the second P also. Like AP_LE.
I got another solution myself.
It has 3 text boxes txtInput, txtOutput, txtKeyPos and a command button command1
Code:
Private Sub Command1_Click()
t1 = Left$(txtInput.Text, Int(txtKeyPos.Text) - 1)
t2 = Right$(txtInput.Text, (Len(txtInput.Text)) - Int(txtKeyPos.Text))
txtOutput.Text = t1 & "_" & t2
End Sub
This serves my purpose.
OK this is vb.net and not vb6 but here goes::
You should do a word approach instead of a character approach:
Dim sentence as String = "My apple is red."
Dim wordsInSentence() as String = sentence.Split()
Dim Rnd as new Random
Dim wordToBlank as String = wordsInSentence(Rnd.next(0, wordsInSentence.length))
Dim blankedSentence as String = sentence.Replace(wordToBlank, "___")
And blankedSentence will contain your sentence with a random word blanked.
My ___ is red.
EDIT: To instead blank a random character in your string, randomise a character index in your string and (if it's not a space) blank that :
Dim sentence as String = "My apple is red."
Dim Rnd as new Random
Dim index As single = Rnd.next(0, sentence.length)
While sentence.Substring(index,1) = " "
index = Rnd.next(0, sentence.length)
End While
Dim blankedSentence as String = sentence.Remove(index,1).Insert(index, "_")
And blankedSentence contains your sentence with a random non-space letter blanked:
My ap_le is red.
This isn't a very good approach though as all letters of all words, including punctuation, can be the character that is blanked. Other than that it will get you what you wanted.
VB6 version:
Dim sentence as String
Dim index As Integer
Dim intUpperBound As Integer
Dim intLowerBound As Integer
sentence = "My apple is red."
intLowerBound = 1 'assuming the first character of the word
intUpperBound = Len(sentence)
Randomize 'initialize the random number generator
index = Int((intUpperBound - intLowerBound + 1) * Rnd) + intLowerBound
While Mid$(sentence, index, 1) = " "
index = Int((intUpperBound - intLowerBound + 1) * Rnd) + intLowerBound
Wend
Dim blankedSentence As String
blankedSentence = sentence
Mid(blankedSentence, index, 1) = "_" 'replace the current character at index with the new character
I'm trying to find a way to easily split a path (Raw URL) in two portions:
For example: /search/criteria/newyork/list
I would like to populate a string that would contain everything before third slash, in this case: "/search/criteria"
I also want to get the second portion into a string: "newyork/list"
You can use IndexOf to find the third slash (assuming that the first character is always the first slash, and that there are at least three slashes in the string):
Dim index3 = url.IndexOf("/"c, url.IndexOf("/"c, 1) + 1)
Then you can use Substring to get the parts before and after that slash:
Dim path As String = url.Substring(0, index3)
Dim resource As String = url.Substring(index3 + 1)
Try this:
Dim sAux() As String = sURL.Split("/"c)
Dim sResult As String = ""
If sAux.Length > 3 Then
For i As Integer = 2 to sAux.Length - 1
sResult &= sAux(i) & "/"
Next
End If
Or this:
Dim sAux As New List(Of String)(sURL.Split("/"c))
sAux.RemoveRange(0,2)
sResult = String.Join("/", sAux.ToArray())
Dim ar As String()
Dim str1 As String
Dim str2 As String
Dim a As Integer
Dim splitPosition = 3
Dim urlToSplit = "/search/criteria/newyork/list"
ar = urlToSplit.Split("/"c)
If UBound(ar) < splitPosition Then
' there are 3 or less slashes. do what you want here, error or just exit
Else
For a = 0 To splitPosition - 1
If Not String.IsNullOrEmpty(ar(a)) Then str1 += ar(a) + "/"
Next
For a = splitPosition To UBound(ar)
If Not String.IsNullOrEmpty(ar(a)) Then str2 += ar(a) + "/"
Next
End If
str1 will contain /search/criteria/
str2 will contain newyork/list/
This code will handle any number of / combinations and should not error out for a badly formed Url
If your string is always in the same format and has same number of elements (in splited array), you could use String.Format method as;
Dim arr() As String = "/search/criteria/newyork/list".Split("/"c)
Dim str1 As String = String.Format("/{1}/{2}", arr) '/search/criteria
Dim str2 As String = String.Format("{3}/{4}", arr) 'newyork/list
I need to
a) separate strings from numbers for a selection of cells
and
b) place the separated strings and numbers into different columns.
For example , Excel sheet is as follows:
A1 B1
100CASH etc.etc.
The result should be:
A1 B1 C1
100 CASH etc.etc.
Utilization of regular expressions will be useful, as there may be different cell formats,such as 100-CASH, 100/CASH, 100%CASH. Once the procedure is set up it won't be hard to use regular expressions for different variations.
I came across a UDF for extracting numbers from a cell. This can easily be modified to extract string or other types of data from cells simply changing the regular expression.
But what I need is not just a UDF but a sub procedure to split cells using regular expressions and place the separated data into separate columns.
I've also found a similar question in SU, however it isn't VBA.
See if this will work for you:
UPDATED 11/30:
Sub test()
Dim RegEx As Object
Dim strTest As String
Dim ThisCell As Range
Dim Matches As Object
Dim strNumber As String
Dim strText As String
Dim i As Integer
Dim CurrCol As Integer
Set RegEx = CreateObject("VBScript.RegExp")
' may need to be tweaked
RegEx.Pattern = "-?\d+"
' Get the current column
CurrCol = ActiveCell.Column
Dim lngLastRow As Long
lngLastRow = Cells(1, CurrCol).End(xlDown).Row
' add a new column & shift column 2 to the right
Columns(CurrCol + 1).Insert Shift:=xlToRight
For i = 1 To lngLastRow ' change to number of rows to search
Set ThisCell = ActiveSheet.Cells(i, CurrCol)
strTest = ThisCell.Value
If RegEx.test(strTest) Then
Set Matches = RegEx.Execute(strTest)
strNumber = CStr(Matches(0))
strText = Mid(strTest, Len(strNumber) + 1)
' replace original cell with number only portion
ThisCell.Value = strNumber
' replace cell to the right with string portion
ThisCell.Offset(0, 1).Value = strText
End If
Next
Set RegEx = Nothing
End Sub
How about:
Sub UpdateCells()
Dim rng As Range
Dim c As Range
Dim l As Long
Dim s As String, a As String, b As String
''Working with sheet1 and column C
With Sheet1
l = .Range("C" & .Rows.Count).End(xlUp).Row
Set rng = .Range("C1:C" & l)
End With
''Working with selected range from above
For Each c In rng.Cells
If c <> vbNullString Then
s = FirstNonNumeric(c.Value)
''Split the string into numeric and non-numeric, based
''on the position of first non-numeric, obtained above.
a = Mid(c.Value, 1, InStr(c.Value, s) - 1)
b = Mid(c.Value, InStr(c.Value, s))
''Put the two values on the sheet in positions one and two
''columns further along than the test column. The offset
''can be any suitable value.
c.Offset(0, 1) = a
c.Offset(0, 2) = b
End If
Next
End Sub
Function FirstNonNumeric(txt As String) As String
With CreateObject("VBScript.RegExp")
.Pattern = "[^0-9]"
FirstNonNumeric = .Execute(txt)(0)
End With
End Function