Excel 2010 VBA - Split String by Comma, Skip Blank Results - arrays

I am using the following code to chop up a column of comma-separated lists and to return each entry in a new row:
Sub SliceNDice()
'
' Splits the locations cells according to commas and pushes to new rows
' Code courtesy of brettdj (http://stackoverflow.com/questions/8560718/split-comma-separated-entries-to-new-rows)
'
Dim objRegex As Object
Dim x
Dim Y
Dim lngRow As Long
Dim lngCnt As Long
Dim tempArr() As String
Dim strArr
Set objRegex = CreateObject("vbscript.regexp")
objRegex.Pattern = "^\s+(.+?)$"
'Define the range to be analysed
x = Range([a1], Cells(Rows.Count, "c").End(xlUp)).Value2
ReDim Y(1 To 3, 1 To 1000)
For lngRow = 1 To UBound(x, 1)
'Split each string by ","
tempArr = Split(x(lngRow, 3), ",")
For Each strArr In tempArr
lngCnt = lngCnt + 1
'Add another 1000 records to resorted array every 1000 records
If lngCnt Mod 1000 = 0 Then ReDim Preserve Y(1 To 3, 1 To lngCnt + 1000)
Y(1, lngCnt) = x(lngRow, 1)
Y(2, lngCnt) = x(lngRow, 2)
Y(3, lngCnt) = objRegex.Replace(strArr, "$1")
Next
Next lngRow
'Dump the re-ordered range to columns E:G
[e1].Resize(lngCnt, 3).Value2 = Application.Transpose(Y)
End Sub
While this code works perfectly, it has a fatal flaw in that any double-commas in the cells of column C will result in blank cells pushed to the new rows in column G.
Does anyone know how to edit the code so that it does not create new rows with empty cells in column G, but skips them and enters the next rows in their places as if the superfluous commas were never included in column C at all?

Just test for the string length of strArr as the first operation inside the For Each strArr In tempArr loop.
For Each strArr In tempArr
If CBool(Len(strArr)) Then
lngCnt = lngCnt + 1
'Add another 1000 records to resorted array every 1000 records
If lngCnt Mod 1000 = 0 Then ReDim Preserve Y(1 To 3, 1 To lngCnt + 1000)
Y(1, lngCnt) = x(lngRow, 1)
Y(2, lngCnt) = x(lngRow, 2)
Y(3, lngCnt) = objRegex.Replace(strArr, "$1")
End If
Next strArr

You could loop on the occurence of double comma to clean up the input as opposed to fixing the output, here is a working example:
Text in A1: Hello,,World,This,,Is,,,,,,,A,,Test
Sub TestString()
Dim MyString As String
MyString = Range("A1").Text
Do Until Len(MyString) = Len(Replace(MyString, ",,", ","))
MyString = Replace(MyString, ",,", ",")
Loop
MsgBox MyString
End Sub
You would do this just before splitting
If you want it as a function (would be better in your case) do this:
Function FixDoubleComma(MyString As String)
Do Until Len(MyString) = Len(Replace(MyString, ",,", ","))
MyString = Replace(MyString, ",,", ",")
Loop
FixDoubleComma = MyString
End Function
Then replace this in your code:
tempArr = Split(x(lngRow, 3), ",")
With this:
tempArr = Split(FixDoubleComma(x(lngRow, 3)), ",")

I have a little sample that solves blanks everywhere
Sub RemoveBlanks()
Dim mystr As String
Dim arrWithBlanks() As String
Dim arrNoBlanks() As String
Dim i As Integer
mystr = ",tom,jerry, ,,spike,," 'Blanks everywhere (beginning, middle and end)
arrWithBlanks = Split(mystr, ",")
ReDim arrNoBlanks(0 To 0)
Debug.Print "Array with blanks:"
'Loop through the array with blanks
For i = LBound(arrWithBlanks) To UBound(arrWithBlanks)
'Check if there is a blank (or element with spaces only)
If Trim(arrWithBlanks(i)) = "" Then
Debug.Print i & " (blank)"
Else
Debug.Print i & " " & arrWithBlanks(i)
If arrNoBlanks(UBound(arrNoBlanks)) <> "" Then ReDim Preserve arrNoBlanks(0 To UBound(arrNoBlanks) + 1)
arrNoBlanks(UBound(arrNoBlanks)) = arrWithBlanks(i)
End If
Next i
Debug.Print "Array with NO blanks:"
For i = LBound(arrNoBlanks) To UBound(arrNoBlanks)
Debug.Print i & " " & arrNoBlanks(i)
Next i
End Sub
Everything will be displayed in the immediate window (Press Ctrl + G to show it)
The result will look like this:
Array with blanks:
0 (blank)
1 tom
2 jerry
3 (blank)
4 (blank)
5 spike
6 (blank)
7 (blank)
Array with NO blanks:
0 tom
1 jerry
2 spike

Related

Array is blank when creating from entries in a column

This code creates an array off a range.
When I try to see if the array is saving the elements, by using Debug.Print, nothing is shown in the Immediate Window. It displays blank spaces. There are no errors.
This only happens in that part of the code, the first Debug.Print line works. I do have data in the columns.
Dim myArray() As Variant
Dim iCountLI As Long
Dim iElementLI As Long
If IsEmpty(Range("B3").Value) = True Then
ReDim myArray(0, 0)
Else
iCountLI = Sheets("Sheet1").Range("B3").End(xlDown).Row
iCountLI = (Range("B3").End(xlDown).Row) - 2
Debug.Print iCountLI
ReDim myArray(iCountLI)
For iElementLI = 1 To iCountLI
myArray(iElementLI - 1) = Cells(iElementLI + 2, 2).Value
Debug.Print myArray(iElementLI)
Next iElementLI
End If
Immediate problem: ReDim myArray(iCountLI) creates an array with empty values. In the For Loop, myArray(iElementLI - 1) = Cells(iElementLI + 2, 2).Value overwrites the first, second, etc. values, yet your Debug.Print myArray(iElementLI) is printing the second, third, etc. values. These, of course, haven't yet been overwritten, so they are still empty. The easiest fix, then, is to use Debug.Print myArray(iElementLI - 1).
More generally, I think you might be misunderstanding the meaning of ReDim myArray(iCountLI). Let's assume we have values in B3:B7. This would lead to ReDim myArray(5) in your code, but this is an array with 6 empty values, at location 0,1,2,3,4,5. This means you will keep an empty value trailing in the array after your loop, which is probably not what you want.
Here's a suggested rewrite with some comments:
Sub FillArray()
Dim myArray() As Variant
Dim iCountLI As Long
Dim iElementLI As Long
'let's assume: B3:B7 with values: 1,2,3,4,5
If IsEmpty(Range("B3").Value) = True Then
ReDim myArray(0, 0)
Else
'iCountLI = Sheets("Sheet1").Range("B3").End(xlDown).Row
'this line serves no purpose: you are immediately reassigning the value in the next line
'iCountLI = (Range("B3").End(xlDown).Row) - 2 'This would be 5,
'but myArray(5) would have SIX elements
iCountLI = (Range("B3").End(xlDown).Row) - 3
Debug.Print iCountLI '4
ReDim myArray(iCountLI)
'For iElementLI = 1 To iCountLI
For iElementLI = 0 To iCountLI '0 to 4
myArray(iElementLI) = Cells(iElementLI + 3, 2).Value 'starting at 0, so "+3", not "+2"
'myArray(iElementLI - 1) = Cells(iElementLI + 2, 2).Value
Debug.Print myArray(iElementLI) 'in succession: 1,2,3,4,5
Next iElementLI
End If
End Sub
Finally, it is worth pointing out that you don't actually need a For Loop to populate an array with values from a range. You could use something as follows:
Sub FillArrayAlt()
Dim myArray() As Variant
Dim iCountLI As Long
Dim iElementLI As Long
Dim myRange As Range
'let's assume: B3:B7 with values: 1,2,3,4,5
If IsEmpty(Range("B3").Value) = True Then
ReDim myArray(0, 0)
Else
Set myRange = Range("B3:" & Range("B3").End(xlDown).Address)
myArray = Application.Transpose(myRange.Value)
'N.B. Confusingly, used in this way, your array WILL start at 1!
For i = LBound(myArray) To UBound(myArray)
Debug.Print i; ":"; myArray(i)
' 1 : 1
' 2 : 2
' 3 : 3
' 4 : 4
' 5 : 5
Next i
End If
End Sub
You are valuing myArray(iElementLI -1) and printing myArray(iElementLI), which is still empty.

Make a new array that contains only selected rows from a previous array based on a variable in a column

I'm trying to make a new array that contains only selected values from a previous array based on a variable.
For instance, I have this as an array:
Using a selection box from a user form, I want to be able to pick item # 15 for instance (in column 1) and get a new array of just the rows that contain item # 15 (new array would be 3 rows by 9 columns).
any ideas how to do that? also allowing it to be dynamic since I want to be able to do this for different sets of Data. I'm not sure if it would be better to sort on two columns column 1 which is item # and the last column that corresponds to what sheet it is on.
Please try this code. It should be installed in a standard code module. Adjust the enumerations at the top to show where the data are (presumed to be at A2:I13). The code asks you to specify an Item to extract and will print the extracted data to an area 5 rows below the original.
Option Explicit
Enum Nws ' worksheet navigation
' modify as required
NwsFirstDataRow = 2
' columns and Array elements:-
NwsItm = 1 ' indicate column A
NwsTab = 9 ' indicate column I
End Enum
Sub Test_DataSelection()
Dim Ws As Worksheet
Dim Rng As Range
Dim Arr As Variant
Dim Itm As String
Set Ws = ThisWorkbook.Worksheets("Sheet1") ' modify as required
With Ws
Set Rng = .Range(.Cells(NwsFirstDataRow, NwsItm), _
.Cells(.Rows.Count, NwsTab).End(xlUp))
End With
Arr = Rng.Value
Itm = InputBox("Enter a valid Item number", "Select data", 5)
Arr = SelectedData(Itm, Arr)
With Ws ' may specify another sheet here
Set Rng = .Cells(.Rows.Count, NwsItm).End(xlUp).Offset(5)
Rng.Resize(UBound(Arr), UBound(Arr, 2)).Value = Arr
End With
End Sub
Function SelectedData(ByVal Itm As Variant, _
Arr As Variant) As Variant()
' Variatus #STO 21 Jan 2020
Dim Fun() As Variant
Dim Ub As Long
Dim i As Long
Dim R As Long, C As Long
On Error Resume Next
Ub = UBound(Arr)
If Err.Number = 0 Then
On Error GoTo 0
Itm = Val(Itm)
ReDim Fun(1 To UBound(Arr, 2), 1 To Ub)
For R = 1 To Ub
If Arr(R, 1) = Itm Then
i = i + 1
For C = 1 To UBound(Arr, 2)
Fun(C, i) = Arr(R, C)
Next C
End If
Next R
ReDim Preserve Fun(1 To UBound(Fun), 1 To i)
End If
SelectedData = Application.Transpose(Fun)
End Function
HerLow
A basic idea that you might be able to adapt to your needs…..to answer this …. I want to be able to pick item # 15 for instance (in column 1) and get a new array of just the rows that contain item # 15 (new array would be 3 rows by 9 columns).
Option Explicit
Sub ArrayBasedOnRowSelection()
Dim WsList As Worksheet, WsOut As Worksheet
Set WsList = ThisWorkbook.Worksheets("List"): Set WsOut = ThisWorkbook.Worksheets("Output")
Dim arrIn() As Variant, arrOut() As Variant
Let arrIn() = WsList.UsedRange
Dim Cnt As Long, strRws As String
For Cnt = 2 To WsList.UsedRange.Rows.Count
If arrIn(Cnt, 1) = "15" Then
Let strRws = strRws & Cnt & " "
Else
End If
Next Cnt
Let strRws = Left$(strRws, Len(strRws) - 1)
Dim SptStr() As String: Let SptStr() = Split(strRws, " ", -1, vbBinaryCompare)
Dim RwsT() As String: ReDim RwsT(1 To UBound(SptStr()) + 1, 1 To 1)
For Cnt = 1 To UBound(SptStr()) + 1
Let RwsT(Cnt, 1) = SptStr(Cnt - 1)
Next Cnt
Dim Clms() As Variant: Let Clms() = Evaluate("=Column(A:" & CL(WsList.UsedRange.Columns.Count) & ")") ' Evaluate("=Column(A:I)")
Let arrOut() = Application.Index(arrIn(), RwsT(), Clms())
WsOut.Cells.Clear
Let WsOut.Range("A2").Resize(UBound(arrOut(), 1), WsList.UsedRange.Columns.Count).Value = arrOut
End Sub
' http://www.excelfox.com/forum/showthread.php/1902-Function-Code-for-getting-Column-Letter-from-Column-Number?p=8824&viewfull=1#post8824
Public Function CL(ByVal lclm As Long) As String ' http://www.excelforum.com/development-testing-forum/1101544-thread-post-appendix-no-reply-needed-please-do-not-delete-thanks-4.html#post4213980
Do: Let CL = Chr(65 + (((lclm - 1) Mod 26))) & CL: Let lclm = (lclm - (1)) \ 26: Loop While lclm > 0
End Function
If you run that macro , it will paste out an array 3 rows by as many columns as your used range in worksheet “List”, based on the selection 15 from column 1.
File: ArrayfromRowsBasedOnPreviousArray.xlsm : https://app.box.com/s/h9ipfz2ngskjn1ygitu4zkqr1puuzba1
Explanation : https://www.excelforum.com/excel-new-users-basics/1099995-application-index-with-look-up-rows-and-columns-arguments-as-vba-arrays.html#post4571172
Alan

Increment different counters depending on array index value

I have a vast list of data in a worksheet (called MainDump). I have a procedure set up to assess this list and return certain values using the following setup:
Dim ws1 As Worksheet
Set ws1 = Worksheets("DashBoard")
Dim ws2 As Worksheet
Set ws2 = Worksheets("MainDump")
Dim cntr As Long
On Error GoTo ErrorHandler 'Got A lot of divide by zero errors if searchstring wasn't found
With Application.WorksheetFunction
ws1.Range("O4").Value = .CountIf(ws2.Range("E:E"), "*" & "CEOD" & "*")
ws1.Range("L4").Value = .CountIfs(ws2.Range("E:E"), "*" & "CEOD" & "*", ws2.Range("A:A"), "Yes") / ws1.Range("O4").Value
ws1.Range("M4").Value = .CountIfs(ws2.Range("E:E"), "*" & "CEOD" & "*", ws2.Range("B:B"), "Yes") / ws1.Range("O4").Value
ws1.Range("N4").Value = .CountIfs(ws2.Range("E:E"), "*" & "CEOD" & "*", ws2.Range("C:C"), "SA Present, WBDA Present") / ws1.Range("O4").Value
End With
cntr = cntr + 1
'^This proces is then copied and thus repeated a total of 76 times, as I want to check
'for 76 different values in ws2.Range("E:E"), resulting in a massive code
ErrorHandler:
If Err.Number = 6 Then
If ws1.Range("O" & cntr).Value = 0 Then
ws1.Range("L" & cntr).Value = "div. by zero"
ws1.Range("M" & cntr).Value = "div. by zero"
ws1.Range("N" & cntr).Value = "div. by zero"
End If
End If
Resume Next
I wrote this when I was a lot less experienced in VBA. Needless to say this code takes a lot of time to complete (Maindump counts about 98000 rows).
So I wanted to try do this work via an array.
My approach would be to define a counter for each string I want to check in the array indexes and then looping through the array and increment the corresponding counters when a string is found in the Array. My question is if there is a way to write that loop in the following form:
Dim LastRow1 As long
Dim DataArray() As Variant
Dim SearchString1, SearchString2, .... SearchString76 As String
Dim SearchString1Cntr, SearchString2Cntr, .... SearchString76Cntr As long
With ws2
LastRow1 = .Cells.Find(What:="*", After:=.Range("A1"), LookAt:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False).Row 'Gets the total row amount in the sheet
DataArray = .Range("A3:E" & LastRow1) 'puts selected range in Array
End With
For LastRow1 = Lbound(DataArray, 1) to Ubound(DataArray, 1)
'Start a For Each loop to check for all 76 strings
If Instr(1, DataArray(LastRow1, 5), SearchString > 0 Then 'SearchString is found so then
SearchStringCntr1 = SearchStringcntr1 + 1
'Where SearchStrinCntr1 is the counter related to the string checked for in the loop,
'so it switches when the SearchString changes
End If
'Next SearchString to check
Next LastRow1
So I want to try and use a flexible If statement in a For Next loop which checks the Array index for each SearchString and then increments the corresponding SearchStringCntr if the SearchString is found in the index, before looping to the next index. Is this possible? I would like to prevent making 76 different If/ElseIf statements for each SearchString + StringCntr and then use a counter to loop through them every time the code loops through the For LastRow1 / Next LastRow1 loop. Would love to hear your input.
Maybe this will help (might need some adjustments).
Create named range "Strings" somewhere in your workbook where you'll store all your strings that you're looking for
Option Explicit
Sub StringsCompare()
Dim LastRow1 As Long
Dim DataArray() As Variant, StringArray() As Variant
Dim Ws2 As Worksheet
Dim CompareStringsNo As Long, StringCounter As Long
Dim i As Long, j As Long
Dim aCell As Range
Dim SourceStr As String, SearchStr As String
Set Ws2 = ThisWorkbook.Sheets("Sheet1")
StringCounter = 1
With Ws2
'fill array with your strings to compare
CompareStringsNo = .Range("Strings").Rows.Count
ReDim StringArray(1 To CompareStringsNo, 1 To 2)
For Each aCell In .Range("Strings")
StringArray(StringCounter, 1) = aCell.Value
StringCounter = StringCounter + 1
Next aCell
'fill data array
LastRow1 = .Cells.Find(What:="*", After:=.Range("A1"), LookAt:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False).Row 'Gets the total row amount in the sheet
DataArray = .Range("A1:E" & LastRow1)
End With
'search data array
For i = LBound(DataArray, 1) To UBound(DataArray, 1)
SourceStr = DataArray(i, 5)
'search array with your strings
For j = LBound(StringArray) To UBound(StringArray)
SearchStr = StringArray(j, 1)
If InStr(1, SourceStr, SearchStr) > 0 Then
'if match is found increase counter in array
StringArray(j, 2) = StringArray(j, 2) + 1
'you can add exit for here if you want only first match
End If
Next j
Next i
For i = LBound(StringArray) To UBound(StringArray)
Debug.Print StringArray(i, 1) & " - " & StringArray(i, 2)
Next i
End Sub
I think the main task is being over-complicated.
To check how many times a string occurs within an array you could use a function like this:
Function OccurWithinArray(theArray As Variant, stringToCount As String) As Long
Dim strArr As String
strArr = Join(theArray, " ")
OccurWithinArray = (Len(strArr) - Len(Replace(strArr, stringToCount, _
vbNullString, , , vbTextCompare))) / Len(stringToCount)
End Function
...and a demonstration:
Sub Demo()
Dim test(1 To 3) As String
test(1) = "I work at the Dog Pound."
test(2) = "I eat dogfish regularly."
test(3) = "Steroidogenesis is a thing."
Debug.Print OccurWithinArray(test, "dog")
End Sub
How it works:
Join joins all the elements of the array into one big string.
Len returns the length of the text.
Replace temporarily replaces the removes all occurrences of the search term.
Len returns the "modified" length of the text.
The difference between the two Len's, divided by the length of the string being searched for, is the number aof occurrences of the string within the entire array.
This returns 3 since the search is case-insensitive.
To make the search case-sensitive, remove the word vbTextCompare (in which case this example would return 2.)

using row range to dim array, and use array to iterate through For loop

Please look at my sample data and code to understand what I'm trying to do.
I need to use the value of Cells(, 3) to define a range to populate a Trialnumber(18) array. I need the array to iterate through a For loop, to count filled cells in column H for each trial and print the count to column T in the last row of each trial. I will also need the array for further data analysis in future(Unless someone can come up with a better solution).
At the moment I am experimenting with 3 modules of code, trying to get the desired solution.
Module 2 is the only one with no errors, and prints the value in the right cell, but it is printing the total filled cell count (562), rather than per trial (expected value = 1 or 2).
Module 1 is as follows:
Sub dotcountanalysis()
Dim startpoint As Long
startpoint = 1
Dim lastrow As Long
lastrow = Cells(Rows.Count, 3).End(xlUp).Row
Dim i As Long
With Worksheets("full test")
For i = 1 To 18
For n = startpoint To lastrow + 1
If Cells(n, 3).Value <> "Trial, " & CStr(i) Then
Dim nMinusOne As Long
nMinusOne = n - 1
Dim trialCount As Long
'Set Trialnumber(i-1) = Range(cells(startpoint, 3), cells(n-1, 3))
trialCount = Application.WorksheetFunction.CountA(Range("H" & CStr(startpoint) & ":" & "H" & CStr(nMinusOne)))
Range("T" & CStr(startpoint) & ":" & "T" & CStr(nMinusOne)).Value = trialCount
startpoint = n
Exit For
End If
Next n
Next i
End With
End Sub
It returns a "method _range of object _global falied" error on line: trialCount = Application.WorksheetFunction.CountA(Range("H" & CStr(startpoint) & ":" & "H" & CStr(nMinusOne)))
Module 3 is as follows:
Sub dotcountanalysis3()
Dim pressedCount As Long
Dim myCell As Range
Dim pressedRange As Range
'create trials array
Dim t(18) As Range
'set range for trialnumber (t)
Dim startpoint As Long
startpoint = 1
Dim lastrow As Long
lastrow = Cells(Rows.Count, 3).End(xlUp).Row
For i = 1 To 18
For n = startpoint To lastrow
startpoint = 7
If Cells(n, 3).Value <> "Trial, " & CStr(i) Then
Set t(i - 1) = Range(Cells(startpoint, 3), Cells(n, 3))
n = n + 1
startpoint = n
Exit For
End If
Next n
Next i
'count presses in each trial
With Worksheets("full test")
For i = 0 To 17
pressedCount = Application.WorksheetFunction.CountA _
(.Range(.Cells(t(), "H"), .Cells(.Rows.Count, "H")))
If pressedCount = 0 Then Exit Sub
'make sure there are cells or else the next line will fail
Set pressedRange = .Columns("H").SpecialCells(xlCellTypeConstants)
For Each myCell In pressedRange.Cells
'only loop through the cells containing something
.Cells(myCell.Row, "T").Value = pressedCount
Next myCell
Next i
End With
End Sub
It returns a run-time "type mismatch" error on line: pressedCount = Application.WorksheetFunction.CountA _
(.Range(.Cells(t(), "H"), .Cells(.Rows.Count, "H")))
Edit: I have updated code in mod 3 and updated error.
When counting things I like to use a dictionary object, and arrays are faster than going row by row on the sheet.
This will count unique combinations of Block+Trial: to count only by trial you would just use k = d(r, COL_TRIAL)
Dim dBT As Object 'global dictionary
Sub dotcountanalysis()
'constants for column positions
Const COL_BLOCK As Long = 1
Const COL_TRIAL As Long = 2
Const COL_ACT As Long = 7
Dim rng As Range, lastrow As Long, sht As Worksheet
Dim d, r As Long, k, resBT()
Set sht = Worksheets("full test")
lastrow = Cells(Rows.Count, 3).End(xlUp).Row
Set dBT = CreateObject("scripting.dictionary")
Set rng = sht.Range("B7:H" & lastrow)
d = rng.Value 'get the data into an array
ReDim resBT(1 To UBound(d), 1 To 1) 'resize the array which will
' be placed in ColT
'get unique combinations of Block and Trial and counts for each
For r = 1 To UBound(d, 1)
k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key
dBT(k) = dBT(k) + IIf(d(r, COL_ACT) <> "", 1, 0)
Next r
'populate array with appropriate counts for each row
For r = 1 To UBound(d, 1)
k = d(r, 1) & "|" & d(r, 2) 'create key
resBT(r, 1) = dBT(k) 'get the count
Next r
'place array to sheet
sht.Range("T7").Resize(UBound(resBT, 1), 1) = resBT
'show the counts in the Immediate pane (for debugging)
For Each k In dBT
Debug.Print k, dBT(k)
Next k
End Sub

Compare Two Dynamic String Arrays

I'm looking for a little guidance and experience. I have an VBA module that creates two strings. See below. I want to use an array to compare the two stings and write the successful matches or "no match" for the element to a third array or directly to the worksheet.
The second part of this is a "percent of" match of Arr2 to Arr1. So the below example would be 88%.
> Arr1 result
> 726741,439037,X41033X,X0254XX,X47083X,X0252XX,X50047X,XH5815X
> Arr2 result
> 726742,439037,X41033X,X0254XX,X47083X,X0252XX,X50047X,XH5815X
Any advice would be great.
Here is one way to accomplish the task using simple for loops.
Sub compareStrings()
Dim str1 As String
Dim str2 As String
str1 = "726741,439037,X41033X,X0254XX,X47083X,X0252XX,X50047X,XH5815X"
str2 = "726742,439037,X41033X,X0254XX,X47083X,X0252XX,X50047X,XH5815X"
Dim Arr1 As Variant
Dim Arr2 As Variant
Dim ArrResults As Variant
Arr1 = Split(str1, ",")
Arr2 = Split(str2, ",")
Dim countMatches As Integer
countMatches = 0
ReDim ArrResults(UBound(Arr1))
For i = LBound(Arr1) To UBound(Arr1)
If Arr1(i) = Arr2(i) Then
ArrResults(i) = "Matches"
countMatches = countMatches + 1
Else
ArrResults(i) = "No Match"
End If
Next i
'Print out the results array in debug window
For Each entry In ArrResults
Debug.Print entry
Next entry
Dim ratio As Double
ratio = countMatches / (UBound(Arr1) + 1)
MsgBox (ratio * 100 & "%")
End Sub
Message box will display this:
Immediate window will display the results array values like this:
Try this:
Sub Test()
Dim str1 As String, str2 As String
Dim arr, i As Long, cnt As Long
str1 = "726741,439037,X41033X,X0254XX,X47083X,X0252XX,X50047X,XH5815X"
str2 = "726742,439037,X41033X,X0254XX,X47083X,X0252XX,X50047X,XH5815X"
For i = LBound(Split(str1, ",")) To UBound(Split(str1, ","))
If Not IsArray(arr) Then
arr = Array(IIf(Split(str1, ",")(i) = _
Split(str2, ",")(i), "Match", "NoMatch"))
Else
ReDim Preserve arr(UBound(arr) + 1)
arr(UBound(arr)) = IIf(Split(str1, ",")(i) = _
Split(str2, ",")(i), "Match", "NoMatch")
End If
Next
'~~> Check the array
For i = LBound(arr) To UBound(arr)
Debug.Print arr(i)
If arr(i) = "Match" Then cnt = cnt + 1
Next
'~~> output the percentage
MsgBox Format(cnt / (UBound(arr) + 1), "0.00%")
End Sub

Resources