Comparing two alphanumeric room numbers to determine floor prefix - excel

I have been working on a project for work where I create room lists based on ranges i.e. 1-3,5 returns 1,2,3,5 in new rows on another sheet. I even was able to read another set of ranges from another cell and compare it for doubles. so it the second cell was 1-3 the list would be, 1A, 1B, 2A, 2B, 3A, 3B, 5A. The next step will be to compare numbers in the first range to determine prefixes and suffixes, assign them to a variable, remove them, do the comparisons and re-insert them when writing rows. A good example of a range would be 5N01-5N05 would need to return 5n01, 5n02, 5n03, 5n04, 5n05. Another example of a range would be 10011-X - 10015-x would need to return 10011-x, 10012-x 10013-x, 10014-x, 10015-x
Any help would be appreciated. I have seen examples that have just split all text and numbers but have not stored the number
In my head I would need to write a formula that grabs the first two numbers, starts at the left, makes notes of the position it is comparing and goes down the line until it hits a unique value. The position can be fed back to read the first however many characters and delete them before entering the range formula and then reinserting when writing the list. The same would be done starting from the right to determine suffix so in the last room list it would go
(10011-x - 10015-x)
Left most character 1 is 1, matches both 1st positions, move to next
Next character 2 is 0, matches both 2nd positions, move to next
Next character 3 is 0, matches both 3rd positions, move to next
Next character 4 is 1, matches both 4th positions, move to next
-Next character 5 is 1, does not match both 5th positions, stop
Prefix = characters 1-4 of first number, 1001
Rightmost character 7 is x, matched both 7th position, move to next
-next character 6 is "-", matches both 6th positions, move to next
next character 5 is 1, does not match both 5th positions, stop
suffix = characters 6-7 of first number, -x
That's where I need help. From there I could manage to extract the true range
1-5 after the prefix and suffix is removed and populate them in the list at the end.

Sorry for the broadness. Just have a lot of moving pieces on this doc
I created some code to compare entries and spit out the prefixes and suffixes of room numbers
Here it is. The next step is incorporating this into my other Sub that can read ranges like (1-5,7,9) I want to be able for it to read (3N01-X-3N05-X, 3N07-X)
and I think with the comparing Sub below I am a little closer. I will try to be more direct with my next questions when I post a new one but this is answered
Sub Prefix()
Sheet7.Range("B1").Select
Dim Entry1 As String
Dim Entry2 As String
Dim currentCharacter As String
Dim currentCharacter2 As String
Dim pCount As Integer
Dim pCurrent As String
Dim Prefix As String
Dim pArray(1 To 10) As String
Dim sCount As Integer
Dim sCurrent As String
Dim Suffix As String
Dim sArray(1 To 10) As String
Entry1 = ActiveSheet.Cells.Range("B" & ActiveCell.Row).Value
Entry2 = ActiveSheet.Cells.Range("C" & ActiveCell.Row).Value
For pCount = 1 To Len(Entry1)
currentCharacter = Mid(Entry1, pCount, 1)
currentCharacter2 = Mid(Entry2, pCount, 1)
If currentCharacter = currentCharacter2 Then
pArray(pCount) = currentCharacter
NextRow2 = Sheet7.Cells(Rows.Count, "G").End(xlUp).Row + 1
Sheet7.Cells(NextRow2, "G") = currentCharacter
Else
Prefix = Join(pArray, "")
MsgBox Prefix
GoTo Suffix
End If
Next
Suffix:
For sCount = 1 To Len(Entry1)
currentCharacter = Right(Entry1, sCount)
currentCharacter2 = Right(Entry2, sCount)
If currentCharacter = currentCharacter2 Then
sArray(sCount) = currentCharacter
NextRow2 = Sheet7.Cells(Rows.Count, "G").End(xlUp).Row + 1
Sheet7.Cells(NextRow2, "G") = currentCharacter
Suffix = currentCharacter
Else
MsgBox Suffix
Exit Sub
End If
Next
End Sub

Related

How to split a word whereever there's a number using MS Excel Delimiter

So I have a list of combinations as mentioned below which I needed to be split with an alphabet and a number following it.
I want it to be split as below using MS Excel; Text to Columns Delimit function or any other efficient function-
I tried using Fixed Width which doesn't work if there are 2 or more digits numeric value after the alphabetical character. Is there a way to do this as I have to repeat this for a 13000 combinations?
Since the Text are constant, create a header row of the constants and with your values starting in A1, put this formula in B2 and copy over and down:
=MID($A2,FIND(B$1,$A2),IF(ISNUMBER(--MID($A2,FIND(B$1,$A2)+2,1)),3,2))
Insert a delimiter character where ever the pattern is found then split the modified string into new columns.
Option Explicit
Sub makeSplit()
Dim i As Long, j As Long, str As String, arr As Variant
'set the worksheet
With Worksheets("sheet5")
'step throughj the cells in column A
For i = .Cells(.Rows.Count, "A").End(xlUp).Row To 2 Step -1
'put the cell value into a variable
str = .Cells(i, "A").Value2
'step through the characters in the sting backwards
For j = Len(str) - 1 To 3 Step -1
'is the current character alphabetic and the previous character a digit?
If Not IsNumeric(Mid(str, j, 1)) And IsNumeric(Mid(str, j - 1, 1)) Then
'insert a space
str = Left(str, j - 1) & Space(1) & Mid(str, j)
End If
Next j
'split the string using the space as delimiter
.Cells(i, "A").Resize(1, UBound(Split(str, Space(1))) + 1) = Split(str, Space(1))
Next i
End With
End Sub
I found a way but is going to be resource intensive.
First have in a sheet all your strings in a column, and make sure you have columns free right to that column.
Then make a new, empty, first row, and put in the letters R, C, P, D, O, S, since you said they are always in that order. These are the recognition letters, needed for the formula.
Now under each letter, right of each string, put in the formula
=C$1&MAX(IFERROR(VALUE(MID($A2,SEARCH(C$1,$A2)+1,2)),0),VALUE(MID($A2,SEARCH(C$1,$A2)+1,1)),0)
This works only if the numbers are no longer then 2 digits, for three it would be
=C$1&MAX(IFERROR(VALUE(MID($A2,SEARCH(C$1,$A2)+1,3)),0),IFERROR(VALUE(MID($A2,SEARCH(C$1,$A2)+1,2)),0),VALUE(MID($A2,SEARCH(C$1,$A2)+1,1)),0)
For four, keep on adding an IFERROR() with the )),2) )),3) increasing like above.
Once all the formulas have evaluated, you can copy and paste as values if you want to get rid of the formulas.
Example sheet (Dutch Excel):

sum number of a string of a cell that meet certain conditions

I just wonder how to calculate this in vba:
Calculate the first amount of money if it is yes but not calculate the amount if it is no. Imagine there are four cells:
(cell 1) abcbc bcbcbcb cbcbcbc $1000/kskskksks/$2000//1222/1221/11/yes
(cell 2) any words will be here $2300/heyhey hey/ //3232//3232/no
(cell 3) kakjsak dsdsk kdjskj 2323/ $23232/hhehe 22/33/333/yes
(cell 4) kakaka kjsdkj ksjskjds kdjsjkdj 11 223 222/ $1121/ $2121/yes
The algorithm is to check whether is yes or no. Then, on each line, find the first money, beginning with $, the second money on the same line would not take into account.
In this example, the program will take $1000 into account, because it is yes, second line would not be executed since it is no. And the third cell would take the first money (first $), $23232. So, the program will sum $1000+$23232+$1121=$25353
I guess that this is what you want, considering that you are using the first column to place each value and your sheet's name is "Sheet1"
Sub SumFirstAmountIfYes()
Dim AmountSum As Variant ' Declares the AmountSum
lastRow = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row ' Finds the last used row on the first column
For i = 1 To lastRow ' Iterates over the rows to the last row
StringValue = Sheets("Sheet1").Cells(i, 1).Value2 ' Gets the value to a variable
If StringValue Like "*yes" Then ' Checks if the string terminates with "yes"
FirstDollar = InStr(StringValue, "$") ' Finds first dollar symbol "$"
FirstSlashAfterDollar = InStr(FirstDollar, StringValue, "/", 0) ' Finds first slash "\" after the first dollar symbol
FirstAmount = Mid(StringValue, FirstDollar + 1, FirstSlashAfterDollar - FirstDollar - 1) ' Gets the amount of each row
AmountSum = AmountSum + CDec(FirstAmount) ' Adds to the sum variable each found amount
End If
Next
MsgBox (AmountSum) ' Shows the final sum of the amounts
End Sub
This uses split to isolate yes/no and InStr to locate the first currency symbol.
Sub sumYes()
Dim i As Long, str As String, dbl As Double
With Worksheets("Sheet10")
For i = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row
str = LCase(.Cells(i, "A").Value2)
If Split(str, "/")(UBound(Split(str, "/"))) = "yes" Then
If CBool(InStr(1, str, Chr(36))) Then
dbl = dbl + Val(Mid(str, InStr(1, str, Chr(36)) + 1))
End If
End If
Next i
.Cells(2, "B") = dbl
End With
End Sub
Slightly different approach which uses excel array formula assuming your cell values doesn't contain trailing spaces ,
=SUM(IF(RIGHT(A1:A4,1)="s",MID(A1:A4,SEARCH("$",A1:A4)+1,SEARCH("/",A1:A4,SEARCH("$",A1:A4))-SEARCH("$",A1:A4)-1)*1,""))

Excel Parse out a list of numbers from text (several numbers from one cell)

I need to parse out a list of tracking numbers from text in excel. The position in terms of characters will not always be the same. An example:
Location ID 987
Your package is arriving 01/01/2015
Fruit Snacks 706970554628
<http://www.fedex. com/Tracking?tracknumbers=706970554628>
Olive Oil 709970554631
<http://www.fedex. com/Tracking?tracknumbers=709970554631>
Sign 706970594642
<http://www.fedex .com/Tracking?tracknumbers=706970594642>
Thank you for shopping with us!
The chunk of text is located in one cell. I would like the results to either be 3 separate columns or rows looking like this:
706970554628 , 709970554631 , 706970594642
There will not always be the same number of tracking numbers. One cell might have six while another has one.
Thank you for any help!!
I think you'll need some VBA to do this. And it's not going to be super simple stuff. #Gary'sStudent has a great example of grabbing numbers from a big string. If you need something that is more specific to your scenario you'll have to parse the string word by word and have it figure out when it encounters a tracking number in the URL.
Something like the following will do the trick:
Function getTrackingNumber(bigMessage As String, numberPosition As Integer) As String
Dim intStrPos As Integer
Dim arrTrackNumbers() As Variant
'create a variable to hold characters we'll use to identify words
Dim strWorkSeparators As String
strWordSeparators = "()=/<>?. " & vbCrLf
'iterate through each character in the big message
For intStrPos = 1 To Len(bigMessage)
'Identify distinct words
If InStr(1, strWordSeparators, Mid(bigMessage, intStrPos, 1)) > 1 Then 'we found the start of a new word
'if foundTrackNumber is true, then this must be a tracking number. Add it to the array of tracking numbers
If foundTrackNumber Then
'keep track of how many we've found
trackNumbersFound = trackNumbersFound + 1
'redim the array in which we are holding the track numbers
ReDim Preserve arrTrackNumbers(0 To trackNumbersFound - 1)
'add the track
arrTrackNumbers(trackNumbersFound - 1) = strword
End If
'Check to see if the word that we just grabbed is "tracknumber"
If strword = "tracknumbers" Then
foundTrackNumber = True
Else
foundTrackNumber = False
End If
'set this back to nothing
strword = ""
Else
strword = strword + Mid(bigMessage, intStrPos, 1)
End If
Next intStrPos
'return the requested tracking number if it exists.
If numberPosition > UBound(arrTrackNumbers) + 1 Then
getTrackingNumber = ""
Else
getTrackingNumber = arrTrackNumbers(numberPosition - 1)
End If
End Function
This is a UDF, so you can use it in your worksheet as a formula with:
=getTrackingNumber(A1, 1)
Which will return the first tracking number it encounters in cell A1. Consequently the formula
=getTrackingNumber(A1, 2)
will return the second tracking number, and so on.
This is not going to be a speedy function though since it's parsing the big string character by character and making decisions as it goes. If you can wrangle Gary's Student's answer into something workable it'll be much faster and less CPU intensive on larger data. However, if you are getting too many results and need to go at this like a surgeon, then this should get you in the ballpark.
If tracking is always a 12 digit number, then select the cell run run this short macro:
Sub parser117()
Dim s As String, ary, i As Long
With ActiveCell
ary = Split(Replace(Replace(.Text, Chr(10), " "), Chr(13), " "), " ")
i = 1
For Each a In ary
If Len(a) = 12 And IsNumeric(a) Then
.Offset(0, i).Value = a
i = i + 1
End If
Next a
End With
End Sub

Excel Find alphanumeric string from text

I have a column containing multiple string values, like a sentence.
in that sentence i want to find one or all alphanumeric values of 10 or more characters containing atleast one - , and put the resulting values in another column.
For example:
the column containing sentence is like:
upgrade 15.07.2010, old No: WI82-01062. User moved to No: WI12-01012 02.04.2012 to a 2 user network.
or
Upgrade from lite 7/6/07, old No: PTX7-89C367EC5052-01211
Ideally I want a column with values like WI82-01062, WI12-01012 for the first example, and PTX7-89C367EC5052-01211 for the second example.
May be searching for the - in the string and finding the first occurrence of blank space at both ends would help, but I do not have any clue how to write that in excel term.
Thanks
You could probably use a regex like this (there may be better patterns!):
Function ExtractData(r As Variant) As String
Static oRE As Object
Dim sTemp As String
Dim n As Long
Dim matches
If oRE Is Nothing Then
Set oRE = CreateObject("vbscript.regexp")
With oRE
.Pattern = "[A-Za-z0-9\-]{10,}"
.Global = True
End With
End If
Set matches = oRE.Execute(r)
If matches.Count > 0 Then
For n = 1 To matches.Count
sTemp = sTemp & ", " & matches(n - 1)
Next n
ExtractData = Mid$(sTemp, 3)
End If
End Function

How to extract text within a string of text

I have a simple problem that I'm hoping to resolve without using VBA but if that's the only way it can be solved, so be it.
I have a file with multiple rows (all one column). Each row has data that looks something like this:
1 7.82E-13 >gi|297848936|ref|XP_00| 4-hydroxide gi|297338191|gb|23343|randomrandom
2 5.09E-09 >gi|168010496|ref|xp_00| 2-pyruvate
etc...
What I want is some way to extract the string of numbers that begin with "gi|" and end with a "|". For some rows this might mean as many as 5 gi numbers, for others it'll just be one.
What I would hope the output would look like would be something like:
297848936,297338191
168010496
etc...
Here is a very flexible VBA answer using the regex object. What the function does is extract every single sub-group match it finds (stuff inside the parenthesis), separated by whatever string you want (default is ", "). You can find info on regular expressions here: http://www.regular-expressions.info/
You would call it like this, assuming that first string is in A1:
=RegexExtract(A1,"gi[|](\d+)[|]")
Since this looks for all occurance of "gi|" followed by a series of numbers and then another "|", for the first line in your question, this would give you this result:
297848936, 297338191
Just run this down the column and you're all done!
Function RegexExtract(ByVal text As String, _
ByVal extract_what As String, _
Optional separator As String = ", ") As String
Dim allMatches As Object
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
Dim i As Long, j As Long
Dim result As String
RE.pattern = extract_what
RE.Global = True
Set allMatches = RE.Execute(text)
For i = 0 To allMatches.count - 1
For j = 0 To allMatches.Item(i).submatches.count - 1
result = result & (separator & allMatches.Item(i).submatches.Item(j))
Next
Next
If Len(result) <> 0 Then
result = Right$(result, Len(result) - Len(separator))
End If
RegexExtract = result
End Function
Here it is (assuming data is in column A)
=VALUE(LEFT(RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2),
FIND("|",RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2)) -1 ))
Not the nicest formula, but it will work to extract the number.
I just noticed since you have two values per row with output separated by commas. You will need to check if there is a second match, third match etc. to make it work for multiple numbers per cell.
In reference to your exact sample (assuming 2 values maximum per cell) the following code will work:
=IF(ISNUMBER(FIND("gi|",$A1,FIND("gi|", $A1)+1)),CONCATENATE(LEFT(RIGHT($A1,LEN($A1)
- FIND("gi|",$A1) - 2),FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2)) -1 ),
", ",LEFT(RIGHT($A1,LEN($A1) - FIND("gi|",$A1,FIND("gi|", $A1)+1)
- 2),FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1,FIND("gi|", $A1)+1) - 2))
-1 )),LEFT(RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2),
FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2)) -1 ))
How's that for ugly? A VBA solution may be better for you, but I'll leave this here for you.
To go up to 5 numbers, well, study the pattern and recurse manually in the formula. IT will get long!
I'd probably split the data first on the | delimiter using the convert text to columns wizard.
In Excel 2007 that is on the Data tab, Data Tools group and then choose Text to Columns. Specify Other: and | as the delimiter.
From the sample data you posted it looks like after you do this the numbers will all be in the same columns so you could then just delete the columns you don't want.
As the other guys presented the solution without VBA... I'll present the one that does use. Now, is your call to use it or no.
Just saw that #Issun presented the solution with regex, very nice! Either way, will present a 'modest' solution for the question, using only 'plain' VBA.
Option Explicit
Option Base 0
Sub findGi()
Dim oCell As Excel.Range
Set oCell = Sheets(1).Range("A1")
'Loops through every row until empty cell
While Not oCell.Value = ""
oCell.Offset(0, 1).Value2 = GetGi(oCell.Value)
Set oCell = oCell.Offset(1, 0)
Wend
End Sub
Private Function GetGi(ByVal sValue As String) As String
Dim sResult As String
Dim vArray As Variant
Dim vItem As Variant
Dim iCount As Integer
vArray = Split(sValue, "|")
iCount = 0
'Loops through the array...
For Each vItem In vArray
'Searches for the 'Gi' factor...
If vItem Like "*gi" And UBound(vArray) > iCount + 1 Then
'Concatenates the results...
sResult = sResult & vArray(iCount + 1) & ","
End If
iCount = iCount + 1
Next vItem
'And removes trail comma
If Len(sResult) > 0 Then
sResult = Left(sResult, Len(sResult) - 1)
End If
GetGi = sResult
End Function
open your excel in Google Sheets and use the regular expression with REGEXEXTRACT
Sample Usage
=REGEXEXTRACT("My favorite number is 241, but my friend's is 17", "\d+")
Tip: REGEXEXTRACT will return 241 in this example because it returns the first matching case.
In your case
=REGEXEXTRACT(A1,"gi[|](\d+)[|]")

Resources