Good day!
There is a problem:
Selected piece of text. In the allocation is as follows:
, .
Example: book 100, pencil 20, ...
I would like to find the sum of the numbers in the row and write it at the end, that is,
book 100, the handle 20
$ 120
I'm trying to solve this problem, but does not go ...
It is unclear, for example, how to access the character in the string.
Did so:
While i <> EndOfText
Char = Mid (AllSelectionText, i, 1)
If Char> = "0" And Char <= "9" Then
...
End If
i = i 1
Wend
But it is not very nice ... must have a function like string (i).
How about using regular expressions? You would need to add a reference to Microsoft VBScript Regular Expressions 5.5, and then you could use the following (not tested):
Function sumOfNumbersInText(text As String) As Long
Dim rgx As New RegExp 'creates a new instance of the Regular Expression object
Dim matches As MatchCollection
Dim mtch As Match
Dim sum As Long
sum = 0
rgx.Pattern = "\d+" 'pattern for a sequence of digits
rgx.Global = True 'find all matches within text
Set matches = rgx.Execute(text) 'get collection of all substrings matching the pattern
For Each mtch In matches
sum = sum + CLng(mtch.Value) 'change each substring into a number and add to sum
Next
sumOfNumbersInText = sum
End Function
Related
How do I read the first 1 to 2 integers of a string in a loop? I need to only parse the first integer or the second integer. For example, "8sdr" I only want to parse "8" and then for a "12sdr" I want to parse "12". I need this to be in a loop to be able to continuously parse only the first integers in a string. Thank you!
The following will return any given number of digits from the start of a string:
Function LeadingDigits(text As String, maxDigits As Integer) As String
Dim pos As Integer, c As String
Do Until pos >= maxDigits Or pos >= Len(text)
c = Mid$(text, pos + 1, 1)
If c < "0" Or c > "9" Then Exit Do
pos = pos + 1
Loop
LeadingDigits = Mid$(text, 1, pos)
End Function
Contrary to solutions that rely on IsNumeric() or Val(), this function does not get confused by strings that can be interpreted as numeric, but don't fall into the specification, such as
hexadecimal ("&habc" = 2748)
scientific notation ("3e4" = 30000)
+/- signs at the start of the string
decimal numbers ".5" = 0.5
Only decimal digits 0–9 at the start of the string are accepted.
The function returns a string, not a numeric type (like Integer) so that there can be a separate return value for "nothing found" (the empty string), and so that very long numbers can be returned that would not fit into a numeric data type.
If you need only up to two numbers that occur before a letter I would use RegEx for this:
Public Function FirstTwoNumbersFromStringBeforeLetter(ByVal textNumbers As String) As Long
Dim regEx
Set regEx = CreateObject("vbscript.regexp")
With regEx
.Global = True
.Pattern = "[a-z].*|\D"
FirstTwoNumbersFromStringBeforeLetter = Left(Val(.Replace(textNumbers, vbNullString)), 2)
End With
End Function
I can see numerous posts around this topic but none that specifically solves the problem I have.
I have a string that has text and numbers. I need to split the string into 2 columns when it first sees a number.
Example:
Ballyvic Boru5/6
First Drift2/1
Sizing Cusimanoin15/2
Becomes:
You can use a simple formula to find the first number, along with LEFT and MID to split the string.
Part 1:
=LEFT(A1,MIN(FIND({1,2,3,4,5,6,7,8,9,0},A1&"1234567890"))-1)
Part 2:
=MID(A1,MIN(FIND({1,2,3,4,5,6,7,8,9,0},A1&"1234567890")),99)
Here's a regex method:
You must set a reference to Microsoft VBScript Regular Expressions x.x, where x.x is the highest version you have (mine is 5.5)
Option Explicit
Sub splitCells()
Dim RegEx As New RegExp, i As Long, tempStr As String
With RegEx
.Global = True
.IgnoreCase = True
.Pattern = "(([a-z]*\s?)*\D)(\d.*)"
End With
With ThisWorkbook.Worksheets(1)
For i = 1 To .Cells(.Rows.Count, 1).End(xlUp).Row
If RegEx.Test(.Cells(i, 1)) Then
tempStr = .Cells(i, 1)
.Cells(i, 1) = RegEx.Replace(tempStr, "$1")
.Cells(i, 2) = RegEx.Replace(tempStr, "$3")
End If
Next i
End With
End Sub
Breaking down the Regular Expression:
(([a-z]*\s?)*\D)(\d.*)
[a-z]* matches any character in the alphabet, with the * multiplier for unlimited occurances
\s? Matches any whitespace character, with the ? multiplier to match 0-1 occurances (meaning there may or may not be a white space
Both of the above is enclosed in a grouping (), followed by another * to match 0-unlimited occurances
\D This excludes all digits
The above is enclosed in a group with the first (([..])*\D)
We have our final group: (\d.*), which matches the first digit and everything else afterwards.
Here's a pair functions you can use on the worksheet (as opposed to having to run a VBA procedure to 'fix' the cells one time):
Public Function splitNum1(str As String) As String
Dim p
For p = 1 To Len(str)
If Mid(str, p, 1) Like "#" Then Exit For
Next
splitNum1 = Left(str, p - 1)
End Function
Public Function splitNum2(str As String) As String
splitNum2 = Right(str, Len(str) - Len(splitNum1(str)))
End Function
splitNum1 returns the string on the "left" side of the number.
splitNum2 returns the string beginning with the first nummber.
I'm currently busy with Excel tooling and learning a lot but i got a question. Currently i have a couple rows with data in the rows. In the rows there is a lot of data but i need a specific part of the row. Of course i can delete it all manually but to do that for 3000 rows i will be wasting a lot of time.
Can any one help me with a macro that filters data. The data i need is between [ and ] so for example [data]
I hope you guys can help me out and if you need more information just ask me! I hope you guys can help me!
Example String ROW:
[Sandwitch]><xsd:element name="T8436283"
So what do i need?
So i need a macro that only gets the Sandwitch out of it and paste it in the B column. The string with all the information stays at column A and the Sandwitch goes to Column B and that for all rows.
Option 1: Find/Replace
1) Copy data in another column (just saving original copy)
2) Perform Find/Replace "*["
3) Perform Find/Replace "]"
Now you have data which was between [].
Option 2: Use formulas
1) Lets assume that original data in Column "A"
2) Apply this formula in column "B" which will extract data between []
=MID(A1,FIND("[",A1)+1,FIND("]",A1)-FIND("[",A1)-1)
Option 3: Macro
If it is absolutely needed, I can help create a macro, otherwise try first two easier options.
A general purpose "find element in s starting x up to next y":
Function GenExtract(FromStr As String, _
StartSep As String, EndSep As String) _
As Variant
Dim StPos As Long
Dim EnPos As Long
GenExtract = CVErr(xlErrNA)
If StartSep = "" Or EndSep = "" Then Exit Function 'fail
StPos = InStr(1, FromStr, Left(StartSep, 1))
If StPos = 0 Or StPos = Len(FromStr) Then Exit Function 'fail
EnPos = InStr(StPos + 1, FromStr, Left(EndSep, 1))
If EnPos = 0 Then Exit Function 'fail
GenExtract = Mid(FromStr, StPos + 1, EnPos - StPos - 1)
End Function
If the two separators are the same, as per quotes, it gives the first string enclosed by those.
If you want to get your feet wet in Regular Expressions, the following code will take you there. You have to add a reference to the VB Scripting Library
Tools > References > Microsoft VBScript Regular Expressions 5.5
Then the code is as follows:
Sub textBetweenStuffs()
Dim str As String
Dim regEx As RegExp
Dim m As Match
Dim sHolder As MatchCollection
Dim bracketCollection As Collection
Dim quoteCollection As Collection
Set regEx = New RegExp
'Matches anything in between an opening bracket and first closing bracket
regEx.Pattern = "\[(.*?\])"
str = "[Sandwitch]><xsd:element name=""T8436283"""
'populates matches into match collection
Set sHolder = regEx.Execute(str)
Set bracketCollection = New Collection
'loop through values in match collection to do with as you wish
For Each m In sHolder
bracketCollection.Add m.Value
Next i
Set sHolder = Nothing
'get values between Quotations
regEx.Pattern = "\"(.*?\")"
'populates matches into match collection
Set sHolder = regEx.Execute(str)
Set quoteCollection = New Collection
'loop through values in match collection to do with as you wish
For Each m In sHolder
quoteCollection.Add m.Value
Next i
End Sub
How do i get the Index of the last active column in a row using Open Xml
i have this for row 1.
Dim activeCells As IEnumerable(Of DocumentFormat.OpenXml.Spreadsheet.Cell) = row.Descendants(Of DocumentFormat.OpenXml.Spreadsheet.Cell)().Where(Function(c) Not String.IsNullOrEmpty(c.InnerText))
Dim cell As DocumentFormat.OpenXml.Spreadsheet.Cell = activeCells.LastOrDefault()
Dim CellRef As String = cell.CellReference
This gives D1", but what i want is the index in this case "4". how do i go about this?
To convert the cell reference to a column index you could use something like the following (I've converted the code from the answer here which you've inspired me to write :)).
Private Shared Function GetColumnIndex(cellReference As String) As System.Nullable(Of Integer)
If String.IsNullOrEmpty(cellReference) Then
Return Nothing
End If
'remove digits
Dim columnReference As String = Regex.Replace(cellReference.ToUpper(), "[\d]", String.Empty)
Dim columnNumber As Integer = -1
Dim mulitplier As Integer = 1
'working from the end of the letters take the ASCII code less 64 (so A = 1, B =2...etc)
'then multiply that number by our multiplier (which starts at 1)
'multiply our multiplier by 26 as there are 26 letters
For Each c As Char In columnReference.ToCharArray().Reverse()
columnNumber += mulitplier * (CInt(c) - 64)
mulitplier = mulitplier * 26
Next
'the result is zero based so return columnnumber + 1 for a 1 based answer
'this will match Excel's COLUMN function
Return columnNumber + 1
End Function
Note: the VB might not be idiomatic as I used the Telerik Converter to convert it from C# to VB.
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)