I have the following strings: Anaheim Temp. 1-N/A and Cevera-N/A.
How do I get Temp from the first one and Cevera from the second one?
So sorry,I'll try to provide more info: So lets say I want to split the first string to first name and last name so first name would be "Anaheim" last name would be "Temp" second example: "Alex Orellana-NA" so first name would be "Alex" last name "Orellana" how do I get rid of whats coming after special characters like "-" "." "/"
I think I understand what you are asking for. You are looking for a function that will take 2 strings and search one string with a phrase, then return the result if it contains it. I believe I have a solution to your issue:
Public Function FindCertainString(stringToSearch As String, stringToFind As String) As String
For index = 1 To stringToSearch.Length - 1
Dim character As Char = stringToSearch(index)
' Parse through whole string and find any match values
If character = stringToFind(0) Then
' Matched the first letter
Dim tempIndex As Integer = index
Dim someWord As String = ""
For innerIndex = 1 To stringToFind.Length
someWord += stringToSearch(tempIndex)
tempIndex += 1
Next
If someWord = stringToFind Then
' Found the word you were looking for
Return someWord
End If
End If
Next
Return ""
End Function
This should satisfy what you are looking for because what this function will do is take in the two strings then for the stringToSearch it will prase through each character until it identifies a match to the beginning letter in the stringToFind from there it collects together an equal length in characters and examines if it matches the stringToFind value.
Info : This answer is obsolete and was based on the initial question of OP before the Edits.
"Anaheim Temp. 1-N/A".IndexOf("Temp") ' -> returns 8 = found at index 8 !
"Cevera-N/A".IndexOf("Cevera") ' -> returns 0 = found at index 0 !
"Cevera-N/A".IndexOf("Temp") ' -> returns -1 = not found !
"Cevera-N/A".IndexOf("cevera") ' -> returns -1 = not found ! because it's lowercase !
I do agree with the comments above : you didn't provide what's the purpose of finding the specified word, or wether are your looking for a complex logic to confirm the presence of a specific identifer in a literal (Temp or Cereva or any other specific word in ANY provided literal sentence or formula)
We don't know what's the meaning of "Anaheim Temp. 1-N/A", where did that came from, wether it's the value of a string variable or some literal expression of a formula entered in a text box...
You want to find "Temp" in "Anaheim Temp. 1-N/A", it's there already !!! How on earth would we have to search far away, while obviously "Anaheim Temp. 1-N/A" contains "Temp" ?
And there are several ways to know if a String contains another String, but the usefull one depends on where the string "Anaheim Temp. 1-N/A" came from and why the string "Temp" should be found there but not "1" or "-N" or even "SantaMaria", and the purpose of searching that word for...
You haven't tried anything so far if I understand, while you want us to guess the logic behind.. XD
What the following code does is to extract Name components one by one until an invalid character is found.
The Function input is a String which holds the literal names.
The output is a List(Of String) that contains each extracted name component.
Sample test -> Resulting Name Components
"Anaheim Temp. 1-N/A" -> [Anaheim],[Temp]
"Cevera-N/A" -> [Cevera]
"Alex Orellana-NA" -> [Alex],[Orellana]
"Marie J Blige ?" -> [Marie],[J],[Blige]
"Marie J. Blige /vv" -> [Marie],[J.],[Blige]
"José F. 1452" -> [José],[F.]
"P. P. d'Arvor" -> [P.],[P.],[d]
To make "P. P. d'Arvor" work, should include handling of ['] char, which I didn't.
(EDIT : It wasn't about Substrings.)
Public Function GetNames(ByVal SampleName As String) As List(Of String)
Dim CharIndex As Integer = 0
Dim NameStart As Integer = 0
Dim NamesList As New List(Of String)
' Iterate the Chars from the left
While CharIndex < SampleName.Length
If Not Char.IsLetter(SampleName(CharIndex)) Then
If Char.IsWhiteSpace(SampleName(CharIndex)) Then
If CharIndex > NameStart Then
NamesList.Add(SampleName.Substring(NameStart, CharIndex - NameStart))
End If
NameStart = CharIndex + 1
Else
If (SampleName(CharIndex) = "."c) Then
' This, to allow examples like "Angelina J.-N/A"
' "Angelina" will be added first
' then "J." (with the dot) will be added aswell.
If NameStart = (CharIndex - 1) Then
' This simple check prevent the picking of
' two consecutive dots like
' "Jarod R.. Solo" -> "Jarod" and "R." ("Solo" discarded)
' "A. Leo D........" -> "A.", "Leo" and "D."
' ". Andrew" -> "" (break immediately)
NamesList.Add(SampleName.Substring(NameStart, CharIndex - NameStart + 1))
NameStart = CharIndex + 1
Else
If NameStart < CharIndex Then
NamesList.Add(SampleName.Substring(NameStart, CharIndex - NameStart))
End If
Exit While
End If
Else
If NameStart < CharIndex Then
NamesList.Add(SampleName.Substring(NameStart, CharIndex - NameStart))
End If
Exit While ' Discard the rest
End If
End If
End If
CharIndex = CharIndex + 1
End While
Return NamesList
End Function
Then use a Method like this :
Public Sub TestNames()
Dim TestName As String
Dim NameComponents As List(Of String)
TestName = Microsoft.VisualBasic.InputBox("Enter Name") ' lazy me -_-
NameComponents = GetNames(TestName)
' wanna see preview ? un-comment the following.
'TestName = ""
'For Each Word As String In NameComponents
' TestName = TestName + "[" + Word + "]" + Environment.NewLine
'Next
'MessageBox.Show(TestName)
If NameComponents.Count > 1 Then ' You have at least two Names.
' The logic here is up to you
' FirstName = NameComponent.Item(0)
' LastName = NameComponent.Item(1)
ElseIf NameComponents.Count > 0 Then ' You have only one Name.
' FirstName = NameComponent.Item(0)
' LastName = ""
Else
' FirstName = "Unknown"
' LastName = ""
End If
End Sub
EDIT : Fixed the multiple consecutive dots syndrome.
Related
I am trying to create an application which will determine whether a string entered by user is a palindrome or not.
Is it possible to do without StrReverse, possibly with for next loop. That's what i have done so far.
Working one, with StrReverse:
Dim userInput As String = Me.txtbx1.Text.Trim.Replace(" ", "")
Dim toBeComparedWith As String = StrReverse(userInput)
Select Case String.Compare(userInput, toBeComparedWith, True)
Case 0
Me.lbl2.Text = "The following string is a palindrom"
Case Else
Me.lbl2.Text = "The following string is not a palindrom"
End Select
Not working one:
Dim input As String = TextBox1.Text.Trim.Replace(" ", "")
Dim pallindromeChecker As String = input
Dim output As String
For counter As Integer = input To pallindromeChecker Step -1
output = pallindromeChecker
Next counter
output = pallindromeChecker
If output = input Then
Me.Label1.Text = "output"
Else
Me.Label1.Text = "hi"
End If
While using string reversal works, it is suboptimal because you're iterating over the string at least 2 full times (as string reversal creates a copy of a string because strings are immutable in .NET) (plus extra iterations for your Trim and Replace calls).
However consider the essential properties of a palindrome: the first half of a string is equal to the second half of the string in reverse.
The optimal algorithm for checking a palindrome needs only iterate through half of the input string - by comparing value[n] with value[length-n] for n = 0 to length/2.
In VB.NET:
Public Shared Function IsPalindrome(value As String) As Boolean
' Input validation.
If value Is Nothing Then Throw New ArgumentNullException("value")
value = value.Replace(" ", "") // Note String.Replace(String,String) runs in O(n) time and if replacement is necessary then O(n) space.
' Shortcut case if the input string is empty.
If value.Length = 0 Then Return False ' or True, depends on your preference
' Only need to iterate until half of the string length.
' Note that integer division results in a truncated value, e.g. (5 / 2 = 2)...
'... so this ignores the middle character if the string is an odd-number of characters long.
Dim max As Integer = value.Length - 1
For i As Integer = 0 To value.Length / 2
If value(i) <> value(max-i) Then
' Shortcut: we can abort on the first mismatched character we encounter, no need to check further.
Return False
End If
Next i
' All "opposite" characters are equal, so return True.
Return True
End Function
I'm working on extracting twitter/facebook style mentions from a textbox.
So far, here's my code:
Dim a As String = TextBox1.Text + " "
Dim b As Char() = a.ToCharArray
Dim c As String
Dim l As Integer = TextBox1.Text.Length
Dim temp As Integer = 0
Dim nex As Integer = a.IndexOf(" ")
For i = 0 To l - 1
If b(i) = "#" Then
temp = 1
ElseIf temp = 1 Then
temp = 2
End If
If temp = 2 Then
c = a.Substring(i, nex).Trim() 'nex needs be replaced with next space on 2nd or nth loop
MsgBox(c)
temp = 0
nex = a.IndexOf(" ") + nex
End If
Next
Now this works great if the entered text is- #one #twwo #three. (If
the next strings are greater in length.) But doesn't work elsewhere.
Also, there is probably going to be content between two #mentions so I'm not willing to change the b(i).
I'm sure there's a much more efficient way to do this.
Thanks!!
This is a job for regex. The pattern #\w+ should do nicely.
For Each m As Match In Regex.Matches("#testing this is a #test", "#\w+")
Console.WriteLine(m.Value)
Next
Will print out #testing and #test.
This pattern basically means "Find everything that starts with an '#' followed by one or more 'word characters'."
Regex is a very powerful tool for searching strings, you can read more about it on MSDN.
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
I have a list of filenames in a spreadsheet in the form of "Smith, J. 010112.pdf". However, they're in the varying formats of "010112.pdf", "01.01.12.pdf", and "1.01.2012.pdf". How could I change these to one format of "010112.pdf"?
Personally I hate using VBA where worksheet functions will work, so I've worked out a way to do this with worksheet functions. Although you could cram this all into one cell, I've broken it out into a lot of independent steps in separate columns so you can see how it's working, step by step.
For simplicity I'm assuming your file name is in A1
B1 =LEN(A1)
determine the length of the filename
C1 =SUBSTITUTE(A1," ","")
replace spaces with nothing
D1 =LEN(C1)
see how long the string is if you replace spaces with nothing
E1 =B1-D1
determine how many spaces there are
F1 =SUBSTITUTE(A1," ",CHAR(8),E1)
replace the last space with a special character that can't occur in a file name
G1 =SEARCH(CHAR(8), F1)
find the special character. Now we know where the last space is
H1 =LEFT(A1,G1-1)
peel off everything before the last space
I1 =MID(A1,G1+1,255)
peel off everything after the last space
J1 =FIND(".",I1)
find the first dot
K1 =FIND(".",I1,J1+1)
find the second dot
L1 =FIND(".",I1,K1+1)
find the third dot
M1 =MID(I1,1,J1-1)
find the first number
N1 =MID(I1,J1+1,K1-J1-1)
find the second number
O1 =MID(I1,K1+1,L1-K1-1)
find the third number
P1 =TEXT(M1,"00")
pad the first number
Q1 =TEXT(N1,"00")
pad the second number
R1 =TEXT(O1,"00")
pad the third number
S1 =IF(ISERR(K1),M1,P1&Q1&R1)
put the numbers together
T1 =H1&" "&S1&".pdf"
put it all together
It's kind of a mess because Excel hasn't added a single new string manipulation function in over 20 years, so things that should be easy (like "find last space") require severe trickery.
Here's a screenshot of a simple four-step method based on Excel commands and formulas, as suggested in a comment to the answered post (with a few changes)...
This function below works. I've assumed that the date is in ddmmyy format, but adjust as appropriate if it's mmddyy -- I can't tell from your example.
Function FormatThis(str As String) As String
Dim strDate As String
Dim iDateStart As Long
Dim iDateEnd As Long
Dim temp As Variant
' Pick out the date part
iDateStart = GetFirstNumPosition(str, False)
iDateEnd = GetFirstNumPosition(str, True)
strDate = Mid(str, iDateStart, iDateEnd - iDateStart + 1)
If InStr(strDate, ".") <> 0 Then
' Deal with the dot delimiters in the date
temp = Split(strDate, ".")
strDate = Format(DateSerial( _
CInt(temp(2)), CInt(temp(1)), CInt(temp(0))), "ddmmyy")
Else
' No dot delimiters... assume date is already formatted as ddmmyy
' Do nothing
End If
' Piece it together
FormatThis = Left(str, iDateStart - 1) _
& strDate & Right(str, Len(str) - iDateEnd)
End Function
This uses the following helper function:
Function GetFirstNumPosition(str As String, startFromRight As Boolean) As Long
Dim i As Long
Dim startIndex As Long
Dim endIndex As Long
Dim indexStep As Integer
If startFromRight Then
startIndex = Len(str)
endIndex = 1
indexStep = -1
Else
startIndex = 1
endIndex = Len(str)
indexStep = 1
End If
For i = startIndex To endIndex Step indexStep
If Mid(str, i, 1) Like "[0-9]" Then
GetFirstNumPosition = i
Exit For
End If
Next i
End Function
To test:
Sub tester()
MsgBox FormatThis("Smith, J. 01.03.12.pdf")
MsgBox FormatThis("Smith, J. 010312.pdf")
MsgBox FormatThis("Smith, J. 1.03.12.pdf")
MsgBox FormatThis("Smith, J. 1.3.12.pdf")
End Sub
They all return "Smith, J. 010312.pdf".
You don't need VBA. Start by replacing the "."s with nothing:
=SUBSTITUTE(A1,".","")
This will change the ".PDF" to "PDF", so let's put that back:
=SUBSTITUTE(SUBSTITUTE(A1,".",""),"pdf",".pdf")
Got awk? Get the data into a text file, and
awk -F'.' '{ if(/[0-9]+\.[0-9]+\.[0-9]+/) printf("%s., %02d%02d%02d.pdf\n", $1, $2, $3, length($4) > 2 ? substr($4,3,2) : $4); else print $0; }' your_text_file
Assuming the data are exactly as what you described, e.g.,
Smith, J. 010112.pdf
Mit, H. 01.02.12.pdf
Excel, M. 8.1.1989.pdf
Lec, X. 06.28.2012.pdf
DISCLAIMER:
As #Jean-FrançoisCorbett has mentioned, this does not work for "Smith, J. 1.01.12.pdf". Instead of reworking this completely, I'd recommend his solution!
Option Explicit
Function ExtractNumerals(Original As String) As String
'Pass everything up to and including ".pdf", then concatenate the result of this function with ".pdf".
'This will not return the ".pdf" if passed, which is generally not my ideal solution, but it's a simpler form that still should get the job done.
'If you have varying extensions, then look at the code of the test sub as a guide for how to compensate for the truncation this function creates.
Dim i As Integer
Dim bFoundFirstNum As Boolean
For i = 1 To Len(Original)
If IsNumeric(Mid(Original, i, 1)) Then
bFoundFirstNum = True
ExtractNumerals = ExtractNumerals & Mid(Original, i, 1)
ElseIf Not bFoundFirstNum Then
ExtractNumerals = ExtractNumerals & Mid(Original, i, 1)
End If
Next i
End Function
I used this as a testcase, which does not correctly cover all your examples:
Sub test()
MsgBox ExtractNumerals("Smith, J. 010112.pdf") & ".pdf"
End Sub
How would you select the last part of a string starting at a specific character count.
For example I would like to get all text after the 3rd comma. but I get an error saying
"StartIndex cannot be less than zero."
Dim testString As String = "part, description, order, get this text, and this text"
Dim result As String = ""
result = testString.Substring(testString.IndexOf(",", 0, 3))
Heres my two cents:
string.Join(",", "aaa,bbb,ccc,ddd,eee".Split(',').Skip(2));
The code "testString.IndexOf(",", 0, 3)" does not find the 3rd comma. It find the first comma starting at position 0 looking at the first 3 positions (i.e. character positions 0,1,2).
If you want the part after the last comma use something like this:
Dim testString As String = "part, description, order, get this text"
Dim result As String = ""
result = testString.Substring(testString.LastIndexOf(",") + 1)
Note the +1 to move to the character after the comma. You should really also find the index first and add checks to confirm that the index is not -1 and index < testString.Length too.
Alternatives(I assume you want all the text after last comma):
Using LastIndexOf:
' You can add code to check if the LastIndexOf returns a positive number
Dim result As String = testString.SubString(testString.LastIndexOf(",")+1)
Regular Expressions:
Dim result As String = Regex.Replace(testString, "(.*,)(.*)$", "$2")
The third argument of indexOf is the number of charcters to search. You are searching for , starting at 0 for 3 characters - that is searching the string par for a comma which does not exist so the returned index is -1, hence your error. I think that you would need to use some recursion:
Dim testString As String = "part, description, order, get this text"
Dim index As Int32 = 0
For i As Int32 = 1 To 3
index = testString.IndexOf(","c, index + 1)
If index < 0 Then
' Not enough commas. Handle this.
End If
Next
Dim result As String = testString.Substring(index + 1)
The IndexOf function only finds the "First" of the specified character. The last parameter (in your case 3) specifies how many characters to examine and not the occurence.
Refer to Find Nth occurrence of a character in a string
The function specified here finds the Nth occurance of a character. Then use the substring function on the occurance returned.
Alternative , you can also use regular expression to find the nth occurance.
public static int NthIndexOf(this string target, string value, int n)
{
Match m = Regex.Match(target, "((" + value + ").*?){" + n + "}");
if (m.Success)
{
return m.Groups[2].Captures[n - 1].Index;
}
else
{
return -1;
}
}
I think this is what you are looking for
Dim testString As String = "part, description, order, get this text"
Dim resultArray As String() = testString.Split(New Char() {","c}, 3)
Dim resultString As String = resultArray(2)