I'm trying to compare 2 3-digit numbers. This is my current code using nested Ifs
If Mid(Num1, 1, 1) = Mid(Num2, 1, 1) Then
'Check first number against first number
If Mid(Num1, 2, 1) = Mid(Num2, 2, 1) Then
'Check second number against second number
If Mid(Num1, 3, 1) = Mid(Num2, 3, 1) Then
'Check third number against third number
Digits = 3
Else
Digits = 2
End If
And this is just one small part of it. Also, I need to check the order in which they match as well. So whether it's an exact match, all 3 digits match in any order, or if 1 or 2 digits match in any order.
The problem is I have a lot of If statements using this method as I have to compare every combination of digits to check for a 1 digit, 2 digit, 3 digit, etc, match. Is there a better way?
Can be simplified to a function with a simple for loop
Private Function digitMatch(ByVal num1 as String, ByVal num2 as String) As Byte
' num1 and num2 are strings, because of presumption they can start with 0
' (i.e. 042 is valid 3 digit number format, otherwise they can be integers as well)
Dim i As Byte
Dim matches As Byte: matches = 0
For i = 1 To Len(num1)
If InStr(1, num2, Mid(num1, i, 1)) <> 0 Then
matches = matches + 1
End If
Next i
digitMatch = matches
End Function
so eg. digitMatch(023, 053) would return 2
or digitMatch(123, 321) would return 3
In my answer, I return the digits that match, so you can check if there are any and which ones. Also, it works with any number of digits.
Public Function CheckForMatch(ByVal curNum As String, ByVal winNumber As String) As String
Dim i As Long, j As Long
Dim hit As String
hit = vbNullString
For i = 1 To Len(curNum)
j = InStr(1, winNumber, Mid(curNum, i, 1), vbTextCompare)
If j > 0 Then
hit = hit & Mid(curNum, i, 1)
End If
Next i
CheckForMatch = hit
End Function
Public Sub Test()
Dim check As String
check = CheckForMatch("75214", "13672")
If Len(check) > 0 Then
Debug.Print "Numbers " & check & " are a match."
' 721
Else
Debug.Print "No match. Sorry."
End If
End Sub
NOTE: The use of InStr() here was inspired by the answer Rawplus gave before me.
Try this (it will only work correctly if both 'curNum' and 'WinningNumber' are 3 digits long):
'straight match
If curNum = WinningNumber Then
M = 3
s = 3
'matched the first 2 straight
ElseIf InStr(1, WinningNumber, Left(curNum, 2)) > 0 Then
M = 2
s = 2
If InStr(1, WinningNumber, Right(curNum, 1)) > 0 Then M = M + 1
'matched the last 2 straight
ElseIf InStr(2, WinningNumber, Right(curNum, 2)) > 0 Then
M = 2
s = 2
If InStr(1, WinningNumber, Left(curNum, 1)) > 0 Then M = M + 1
'any other scenario
Else
s = 0
For i = 1 To 3
n = Mid(WinningNumber, i, 1)
If InStr(1, curNum, n) > 0 Then
M = M + 1
End If
Next
End If
Debug.Print "Matched digits: " & M
Debug.Print "Straight: " & s
I'm sure there's a better way to do it but this was the easiest way for me to write it up quickly.
Related
0002786961 TRAK CDFA #: 0008787942 2722 2723 4536841 N/A 2786952 4345784 001018809~00077480
Above is an example of data line I need to split these into 3 types:
First column: starts with 2 and is of 4 digit (2722 in above example)
Second: starts with 2 and is of 7 digit(2786952 in above example)
Third: starts with 4 is of 7 digit (4345784 4536841 in above example)
I tried separating everything into different columns and then putting IF AND conditions that I mentioned above but the problem is not everything is getting separated and splitting everything is not efficient enough.
I am not able to figure out a vba code for something that satisfies all the conditions and works too.
Can anyone help me out?
Code tried:
IF(AND(LEFT(A4,1) = "2",LEN(A4) < 5), A4, "No")
This doesn't separate 4 digit numbers in between of text's or numbers.
Tried VBA CODE to extract numbers and text. But for numbers they were all extracted together without space so cant do anything with them.
Function GetNumber(CellRef As String)
Dim StringLength As Integer
StringLength = Len(CellRef)
For i = 1 To StringLength
If IsNumeric(Mid(CellRef, i, 1)) Then Result = Result & Mid(CellRef, i, 1)
Next i
GetNumber = Result
End Function
Function GetText(CellRef As String)
Dim StringLength As Integer
StringLength = Len(CellRef)
For i = 1 To StringLength
If Not (IsNumeric(Mid(CellRef, i, 1))) Then Result = Result & Mid(CellRef, i, 1)
Next i
GetNumber = Result
End Function
Would anyone be kind enough to help?
Quick example (untested)
dim rowNum as long
for rowNum = 1 to 5
dim splitArr as variant
splitArr = split(cells(rowNum, 1).value, " ")
dim elementNum as long
for elementNum = lbound(splitArr) to ubound(splitArr)
checkVal = splitArr(elementNum)
Select case True
Case left(checkVal,1)=2 and len(checkVal)=4
'do something
Case left(checkVal,1)=2 and len(checkVal)=7
'do something
Case left(checkVal,1)=4 and len(checkVal)=7
'do something
End select
next elementNum
next rowNum
I'm trying to format some number data. For each cell within the range I need to replace the first number only with the corresponding letter. 1 = A, 2 = B etc. and then delete the 2nd and 3rd numbers.
So for example:
11111 --> A11
12345 --> A45
23456 --> B56
56789 --> E89
Is there a simple way to do that with formatting? I only need to go up to E.
Here's a little VBA code to accomplish what you need:
s = "56789"
s = Chr(Asc(Mid(s, 1, 1)) + 16) & Mid(s, 4)
My suggestion would be
Option Explicit
Function conA_E(inp As String) As String
Dim res As String
Dim ch As String
On Error GoTo EH
ch = Left(inp, 1)
If ch <= 6 And ch >= 1 Then
res = Chr(Asc(Mid(inp, 1, 1)) + 16) & Mid(inp, 4)
Else
'res = ch & Mid(inp, 4) ' In Case 2nd and 3rd digit should always be deleted
res = inp ' No change if first digit is bigger than 5
End If
conA_E = res
Exit Function
EH:
conA_E = inp
End Function
Sub TestIt()
Dim inp As String
inp = "1214222"
Debug.Print conA_E(inp)
End Sub
I've the following Excel data:
A B C
+ ------------ ------------- -----------------
1 | WORD WORD MIX MATCH TEXT RESULT
2 | somewordsome emsomordsowe ...
3 | anotherword somethingelse ...
4 | ... ... ...
I'd like to:
Firstly, get an array, say ArrayOfGroups, by splitting the string in the A2 cell in unique groups of 2 to 12 adjacent chars (note: 2 is the minimum number of chars to form a group; 12 is the total number of the word's chars) i.e. the groups of 2 chars would be so, om, me, ew, wo, or, rd, ds (note: the last so, om and me groups are excluded because they are repeated); the groups of 3 chars would be som, ome, mew, ewo, wor, ord, rds, dso (last som and ome excluded); the groups of 4 chars would be some, omew, mewo, ewor, word, ords, rdso, dsom; ... and so on until the full string somewordsome.
Then, iterate the above-mentioned ArrayOfGroups to check if each of its element is a substring of the B2 cell and return a new array, say ArrayOfMatches, containing all the elements (the characters "group names") that are substrings of B2 and the number of occurrences found in B2.
Finally, output in the C2 cell a sentence built using the ArrayOfMatches data that says something like this:
2 matches for so, 1 match for som and rd
Probably there are other and better approaches to compute the above sentence that is the final result wanted. Maybe I need to use a User Defined Function... but I never made it.
Is there someone that could give help?
May try something like this
Code edited to avoid counting for same substring found multiple times.
Sub test2()
Dim Xstr As String, Ystr As String
Xstr = "somewordsome"
Ystr = "emsomordsowe"
MsgBox Xmatch2(Xstr, Ystr)
End Sub
Function Xmatch2(Xstr As String, Ystr As String) As String
Dim XSubStr As String, YSubStr As String
Dim xLn As Integer, yLn As Integer
Dim XArr As Variant, LnSubStr As Integer
Dim Rslt As String, Cnt As Integer
Dim Xrr() As Variant, Xcnt As Integer, Chk As Boolean
Rslt = "'"
xLn = Len(Xstr)
yLn = Len(Ystr)
For LnSubStr = 2 To xLn 'length of substring
Xcnt = 0
ReDim XArr(1 To 1)
For Y = 1 To xLn
XSubStr = ""
Xcnt = Xcnt + 1
ReDim Preserve XArr(1 To Xcnt)
If Y + LnSubStr - 1 <= xLn Then XSubStr = Mid(Xstr, Y, LnSubStr)
XArr(Xcnt) = XSubStr
Chk = False
For i = 1 To Xcnt - 1
If XArr(i) = XSubStr Then
Chk = True
Exit For
End If
Next
If XSubStr <> "" And Chk = False Then
Cnt = 0
ReDim Preserve XArr(1 To Xcnt)
For Z = 1 To yLn
YSubStr = ""
If Z + LnSubStr - 1 <= yLn Then YSubStr = Mid(Ystr, Z, LnSubStr)
If YSubStr = XSubStr Then Cnt = Cnt + 1
Next
If Cnt > 0 Then Rslt = Rslt & Cnt & " Matches for " & XSubStr & ","
End If
Next
Next
Debug.Print Rslt
Xmatch2 = Rslt
End Function
Does anyone know a routine on how to get a data set composed by 7 columns into all possible combinations?
the combination is composed by 7 numbers like this--> 1|3|8|10|35|40|50
The routine needs to look into the first table and make a list of all possible combination excluding the duplicate numbers from the combination in the second table. Please see picture.
The table on the left contains the combination which need to be reshuffled, into the right table which contain all possible combinations.
I would do something like:
The number of options are 6^7 so there will be alot of cases: 279936
To get all of it, you should loop through them.
First we should find all the options.
To generate all the possible combinations including duplicates, the probles is the same as get all the may 7 digit long numbers in base 6 ( as we have 6 number in each column)
in newer excels you can use the BASE funtion, but if you can not access it you can use this:
if you cange a code a bit you can call the value of the original table instead of the 0-5 numbers.
Then just remove duplicates.
Sub generateAllBase6()
Dim i As Double 'number tries
Dim n As String ' the number of item from the column 1-7
For i = 0 To 279936 - 1
n = ConvertBase10(i, "012345")
For k = 1 To 7
If Len(n) < k Then
Cells(i + 2, k) = 0
Else
Cells(i + 2, k) = Right(Left(n, k), 1)
End If
Next k
Next i
End Sub
Public Function ConvertBase10(ByVal d As Double, ByVal sNewBaseDigits As String) As String
Dim S As String, tmp As Double, i As Integer, lastI As Integer
Dim BaseSize As Integer
BaseSize = Len(sNewBaseDigits)
Do While Val(d) <> 0
tmp = d
i = 0
Do While tmp >= BaseSize
i = i + 1
tmp = tmp / BaseSize
Loop
If i <> lastI - 1 And lastI <> 0 Then S = S & String(lastI - i - 1, Left(sNewBaseDigits, 1)) 'get the zero digits inside the number
tmp = Int(tmp) 'truncate decimals
S = S + Mid(sNewBaseDigits, tmp + 1, 1)
d = d - tmp * (BaseSize ^ i)
lastI = i
Loop
S = S & String(i, Left(sNewBaseDigits, 1)) 'get the zero digits at the end of the number
ConvertBase10 = S
End Function
I found the funcion here: http://www.freevbcode.com/ShowCode.asp?ID=6604
What it does: I have a section of code which finds a substring TL in a cell, and forces the numbers following it to be of length 6 by adding or deleting 0s immediately following "TL-". (ie TL-00072 -> TL-000072, TL-034 -> TL-000034, TL-000000789 -> TL-000789)
What I want it to do: However, sometimes there are multiple TL values in one cell. I need to find if there is a second occurance of TL, and, if yes, delete that second occurance and everything following it.
Example:
Start: Output:
TL-000789 TL-000187 TL-000773 -> TL-000789
TL-000689 TL -000787 -> TL-000689
TL-000982 TL - 980819 -> TL-000982
This is the attempt at code I have been working on (incorrect and not working) using split (maybe trim would work too?) that would find the second occurence of TL and delete everything after it. Full working code below that.
CURRENT ATTEMPT AT CODE
Dim splitValues As Variant
If Str(str, "TL" + 1) 'do not know how to get SECOND occurrence
splitValues = Split(theValue, "TL")
theValue = splitValues(0)
End If
WORKING CODE
[will add new code to beginning] (explanation at top of question)
NOTE: StartSht is the workbook where the values are as well as the code.
All values being altered are in column "C"
'force length of TL/CT to be 6/4 numbers long, eliminate spaces
Dim str As String, ret As String, tmp As String, j As Integer, k As Integer
For k = 2 To StartSht.Range("C2").End(xlDown).Row
ret = ""
str = StartSht.Range("C" & k).Value
'for TL numbers
''''''''''''''new code goes here''''''''''''''''''
If InStr(str, "TL") > 0 Then
For j = 1 To Len(str)
tmp = Mid(str, j, 1)
If IsNumeric(tmp) Then ret = ret + tmp
Next j
'force to 6 numbers if too short; add 0s immediately after "TL-"
For j = Len(ret) + 1 To 6
ret = "0" & ret
Next j
'force to 6 numbers if too long; eliminate 0s immediately after "TL-"
If Len(ret) > 6 Then
Debug.Print Len(ret)
For j = Len(ret) To 7 Step -1
If Mid(ret, 1, 1) = "0" Then
ret = Right(ret, j - 1)
End If
Next j
End If
'eliminate superfluous spaces around "TL-"
ret = "TL-" & ret
StartSht.Range("C" & k).Value = ret
'for CT numbers
ElseIf InStr(str, "CT") > 0 Then
For j = 1 To Len(str)
tmp = Mid(str, j, 1)
If IsNumeric(tmp) Then ret = ret + tmp
Next j
'force to 4 numbers if too short; add 0s immediately after "CT-"
For j = Len(ret) + 1 To 4
ret = "0" & ret
Next j
'force to 4 numbers if too long; eliminate 0s immediately after "CT-"
If Len(ret) > 4 Then
Debug.Print Len(ret)
For j = Len(ret) To 5 Step -1
If Mid(ret, 1, 1) = "0" Then
ret = Right(ret, j - 1)
End If
Next j
End If
'eliminate superfluous spaces around "CT-"
ret = "CT-" & ret
StartSht.Range("C" & k).Value = ret
End If
Next k
It looks like you could just redefine str if you find a second "TL". After the line:
If InStr(str, "TL") > 0 Then
add another IF statement:
If InStr(3, str, "TL") > 0 Then str = Mid(str, 1, Instr(3, str, "TL") - 2)
Then continue with the rest of your code using the new str.