I want to split a string into 3 parts. For example i have a email adress like
testuser#gamil.com
and i want to split it into
testuser
gamil
.com
with left, right and mid (str) i only can extract a string if is a fixed lenght.
Has anybody some ideas to make it?
with left, right and mid (str) i only can extract a string if is a fixed length.
This is not actually true, because you can also use the len function to get the length of the string.
Dim L as Integer
L = Len("testuser#gamil.com")
MsgBox L
You can also use the Instr (and InstrRev, reversed) function to find the index of a particular character or substring.
Dim I as Integer
I = Instr("testuser#gamil.com", "#")
So, for your case, a custom function without regex will return an array of three items:
Function SplitEmail(email$)
'Function returns an array like:
' {"username", "domain", "tld"}
Dim Dot As Integer, At As Integer
Dot = InStrRev(email, ".")
At = InStr(email, "#")
Dim ret(1 To 3) As String
ret(1) = Left(email, At - 1)
ret(2) = Mid(email, At + 1, Dot - At - 1)
ret(3) = Mid(email, Dot + 1)
SplitEmail = ret
End Function
To get the username part, you could do:
Dim some_email$
some_email = "testuser#gamil.com"
MsgBox SplitEmail(some_email)(1)
Related
I have a column which contain cells that have some list of alphanumeric number system as follows:
4A(4,5,6,7,8,9); 4B(4,5,7,8); 3A(1,2,3); 3B(1,2,3), 3C(1,2)
On a cell next to it, I use a UDF function to get rid of special characters "(),;" in order to leave the data as
4A456789 4B4578 3A123 3B123 3C12
Function RemoveSpecial(Str As String) As String
Dim SpecialChars As String
Dim i As Long
SpecialChars = "(),;-abcdefghijklmnopqrstuvwxyz"
For i = 1 To Len(SpecialChars)
Str = Replace$(Str, Mid$(SpecialChars, i, 1), "")
Next
RemoveSpecial = Str
End Function
For the most part this works well. However, on certain occasions, the cell would contain an unorthodox pattern such as when a space is included between the 4A and the parenthesized items:
4A (4,5,6,7,8,9);
or when a text appears inside the parenthesis (including two spaces on each side):
4A (4,5, skip 8,9);
or a space appears between the first two characters:
4 A(4,5,6)
How would you fix this so that the random spaces are removed except to delaminate the actual combination of data?
One strategy would be to substitute the patterns you want to keep before eliminating the "special" characters, then restore the desired patterns.
From your sample data, it look like you want to keep a space only if it follow ); or ),
Something like this:
Function RemoveSpecial(Data As Variant) As Variant
Dim SpecialChars As String
Dim KeepStr As Variant, PlaceHolder As Variant, ReplaceStr As Variant
Dim i As Long
Dim DataStr As String
SpecialChars = " (),;-abcdefghijklmnopqrstuvwxyz"
KeepStr = Array("); ", "), ")
PlaceHolder = Array("~0~", "~1~") ' choose a PlaceHolder that won't appear in the data
ReplaceStr = Array(" ", " ")
DataStr = Data
For i = LBound(KeepStr) To UBound(KeepStr)
DataStr = Replace$(DataStr, KeepStr(i), PlaceHolder(i))
Next
For i = 1 To Len(SpecialChars)
DataStr = Replace$(DataStr, Mid$(SpecialChars, i, 1), vbNullString)
Next
For i = LBound(KeepStr) To UBound(KeepStr)
DataStr = Replace$(DataStr, PlaceHolder(i), ReplaceStr(i))
Next
RemoveSpecial = Application.Trim(DataStr)
End Function
Another strategy would be regular expressions (RegEx)
It looks like a regular expression could come in handy here, for example:
Function RemoveSpecial(Str As String) As String
With CreateObject("vbscript.regexp")
.Global = True
.Pattern = "\)[;,]( )|[^A-Z\d]+"
RemoveSpecial = .Replace(Str, "$1")
End With
End Function
I have used the regular expression:
\)[;,]( )|[^A-Z\d]+
You can see an online demo to see the result in your browser. The way this works is to apply a form of what some would call "The best regex trick ever!"
\)[;,]( ) - Escape a closing paranthesis, then match either a comma or semicolon before we capture a space character in our 1st capture group.
| - Or use the following alternation:
[^A-Z\d]+ - Any 1+ char any other than in given character class.
EDIT:
In case you have values like 4A; or 4A, you can use:
(?:([A-Z])|\))[;,]( )|[^A-Z\d]+
And replace with $1$2. See an online demo.
I have a column where i pickup increasing numbering values, and their format is xx_yy
so the first is 1_0, second 1_1 and so forth, no we are at 23_31
I want to get the right side of the string, and i am already getting the left side correctly.
using
newActionId = Left(lastActionID, (Application.WorksheetFunction.Find("_", lastActionID, 1) - 1))
i wish to do the following, human writing below
nextSubid = entire stringvalue AFTER special character "_"
I tried just switching left to right, didnt go so well, do you have a suggestion?
You can use Split function to get the relevant text.
Syntax: Split(expression, [ delimiter, [ limit, [ compare ]]])
Option Explicit
Sub Sample()
Dim id As String
Dim beforeSplChr As String
Dim afterSplChr As String
id = "23_31"
beforeSplChr = Split(id, "_")(0)
afterSplChr = Split(id, "_")(1)
Debug.Print beforeSplChr
Debug.Print afterSplChr
End Sub
Another way
Debug.Print Left(id, (InStrRev(id, "_", -1) - 1)) '<~~ Left Part
Debug.Print Right(id, (InStrRev(id, "_", -1) - 1)) '<~~ Right Part
Even though Siddharth Rout has given what can probably be considered a better answer here, I felt that this was worth adding:
To get the second part of the string using your original method, you would want to use the Mid function in place of Left, rather than trying to use Right.
Mid(string, start, [ length ])
Returns length characters from string, starting at the start position
If length is omitted, then will return characters from the start position until the end of the string
newActionId = Mid(lastActionID, Application.WorksheetFunction.Find("_", lastActionID, 1) + 1)
Just for fun (Split is the way to go here), an alternative way using regular expressions:
Sub Test()
Dim str As String: str = "23_31"
With CreateObject("VBScript.RegExp")
.Global = True
.Pattern = "\d+"
Debug.Print .Execute(str)(0) 'Left Part
Debug.Print .Execute(str)(1) 'Right Part
End With
End Sub
Btw, as per my comment, your first value could also be achieved through:
Debug.Print Val(str)
Split function of string is very usefull for this type of query.
Like:
String s = "23_34";
String left = s.split("_")[0];
String right = s.split("_")[1];
Or you can also use combination of indexOf and substring method together.
String left = s.substring(0,s.indexOf('_')+1)
String right = s.substring(s.indexOf('_'));
I have the following input:
Dim str_format as string = "XXXXX00000"
Dim str as string = "INV"
Dim int as integer = "56"
How can I replace XXXXX with INV and replace 00000 with 56?
For the example above the result should be INVXX00056.
X can only replace with alphabet and 0 can only replace with integer, if str has more than five alphabet. The extra alphabets will be thrown away because str_format only has five X. The same algorithm is true for the integer.
Example 2
Dim str_format as string = "XXX00000"
Dim str as string = "ABCD"
Dim int as integer = 654321
Expected result: ABC54321
Process:
1. ABCD XXX00000 654321
2. ABC DXX000006 54321
3. AB CDX00065 4321
4. A BCD00654 321
5. ABC06543 21
6. ABC65432 1
7. ABC54321
As Spidey mentioned... show some code. That said the process you describe is a bit long-winded.
The Letter part of the solution can be done by grabbing the first 3 characters of str using Left(str,3) this will bring in the leftmost 3 character (if there are less it will get what is there). Then check that you have 3 characters using str.Length(). If the length is less than 3 then append the appropriate number of 'X'.
The Numeric part can be done in a similar way. Your int is actually a string in your code above. If it was a real integer you can cast it to string. Use Right(int,5). Again check to see you have 5 digits and if not prepend with appropriate number of 0.
Have a go... if you run into problems post your code and someone is bound to help.
UPDATE
As there have been actual answers posted here is my solution
Function FormatMyString(str As String, num as String) As String
Dim result As String
result = Left(str,3).PadRight(3, "X"c).ToUpper() & Right(num,5).PadLeft(5, "0"c)
Return result
End Function
UPDATE 2
based on Wiktors answer... made an amendment to my solution to cope with different formats
Function FormatMyString(str As String, num as String, alpha as Integer, digits as Integer) As String
Dim result As String
result = Left(str, alpha).PadRight(alpha, "X"c).ToUpper() & Right(num, digits).PadLeft(digits, "0"c)
Return result
End Function
To use...
FormatMyString("ABCDE", "56",3 5) will return ABC00056
FormatMyString("ABCDE", "123456",4 3) will return ABCD456
FormatMyString("AB", "123456",4 3) will return ABXX456
Here is a possible solution that just uses basic string methods and PadLeft/PadRight and a specific method to count occurrences of specific chars in the string. It assumes the format string can only contain X and 0 in the known order.
Public Function CountCharacter(ByVal value As String, ByVal ch As Char) As Integer
Return value.Count(Function(c As Char) c = ch)
End Function
Public Sub run1()
Dim str_format As String = "XXXXX00000" '"XXX00000"
Dim str As String = "INV"
Dim int As Integer = 56 ' ABC54321
Dim xCnt As Integer = CountCharacter(str_format, "X")
Dim zCnt As Integer = CountCharacter(str_format, "0")
Dim result As String
If xCnt > str.Length Then
result = str.PadRight(xCnt, "X")
Else
result = str.Substring(0, xCnt)
End If
If zCnt > int.ToString().Length Then
result = result & int.ToString().PadLeft(zCnt, "0")
Else
result = result & int.ToString().Substring(int.ToString().Length-zCnt
End If
Console.WriteLine(result)
End Sub
Output for your both scenarios is as expected.
Take a look at this sample
Dim str_format As String = str_format.Replace("XXX", "ABC")
Msgbox(str_format )
As we assume that the X is 3 only. I dont want to give you more it is a start and everything will be easy.
If that kind of format is fix I mean the number of X will go or down then you can make a conditional statement based on the length of string
I have an array with some words that i want to replace with other words, in fact, i have some problem:
Eg:
Var1 -> wksArray
Var2 -> wksArrayBigger
string : Dim wksArray, wksArrayBigger as Variant
When i try to replace wksArray with "test1", it will cause:
var1 -> teste1
var2 -> test1Bigger
string : Dim teste1, teste1Bigger as Variant
How can i solve that?
Function FindAndReplace(VBProjToClean, varArray)
Dim i, b As Integer
Dim str, replace_str As String
Dim VBC As VBComponent
For Each VBC In VBProjToClean.VBComponents
i = 1
With VBC.CodeModule
Do Until i > .CountOfLines
If Not .ProcOfLine(i, vbext_pk_Proc) = "VBE_Remove_Comments" Then
str = .Lines(i, 1)
End If
For b = 1 To UBound(varArray)
If InStr(1, str, varArray(b), vbTextCompare) > 0 Then
replace_str = Replace(str, varArray(b), varArray(b) & "banana")
.ReplaceLine i, replace_str
str = .Lines(i, 1)
End If
Next b
i = i + 1
Loop
End With
Next
End Function
While not a proper fix to your problem, you could sort your search list and possibly add some intermediary replacements should there be conflicts you cant resolve.
arrReplaceBigger -> arIM01
arrReplace -> aR
arIM01 -> aRB '
If your just replacing variable names, you could create a function to replace Replace that would do a number of extra replacements, appending however many possibilities for the next character there are.
white-space, comma, period, left bracket, right bracket, new line, plus, ...., etc
Or instead of doing many extra replacements you could do the same thing using Regular Expressions as David suggests.
Write a function to find out if something is a valid character for a VBA variable
Then for each pear of strings,
Look for the occurences of the string to be replaced, verify that preceding and succeding positoins do not contain valid characters, and if so, replace the string.
How do trim off characters in a string, by how much you want?
For example, say your string is "Tony", but you wanted to display "ny" by trimming of the first two characters, how can this be done?
Sub Main()
Dim s As String
Dim Result As String
s = "Tony"
Result = LTrim(s)
msgbox(Result)
I have this so far using the LTrim function, so how do you specify by how much you want to cut to just display "ny" in the MessageBox?
You don't want LTrim. You want Right:
Result = Right(s, Len(s) - 2);
This will take all but the two left-most characters of s.
You could use the additional string functions to do the same thing,
for example:
X$ = RIGHT$(V$, 2) ' get the ending 2 chars of string
X$ = LEFT$(V$, 2) ' get the leading 2 chars of string
X$ = MID$(V$, 2, 2) ' get 2 chars from the inside of string
Well... If I was trying to clip off the beginning of a string, I would use two functions: StrReverse, and Remove.
I would first reverse the string, then use the remove function to cut off what is now the end, Then flip the remaining string back to it's original state using the reverse function again.
The code would look something like this:
Dim s As String = "Anthony"
Dim index As Integer = 2
Debug.Print(StrReverse(StrReverse(s).Remove(2)))
The output of this would be "ny" and the length will correspond to the index.