Find Match between two uneven Variant arrays - excel

I need to check if each string in arr1 has a match in arr2.
If it has a match then write "Match" to the column next to arr1, if not then "Not Match".
Here's how my sheet looks:
Sub Variant_Array_Question()
'Here is my frankenstein monster of a code
Dim DocNm As Variant, NroNm As Variant
Dim i As Long, j As Long
Dim NroLastRow As Long, DocLastRow As Long
'Arr1
DocLastRow = ShStart.Range("Q" & Rows.Count).End(xlUp).Row
DocNm = ShStart.Range("Q6:Q" & DocLastRow).Value
'Arr2
NroLastRow = ShStart.Range("T" & Rows.Count).End(xlUp).Row
NroNm = ShStart.Range("T6:T" & NroLastRow).Value
For i = 1 To UBound(DocNm)
For j = 1 To UBound(NroNm)
If DocNm(i, 1) = NroNm(j, 1) Then
'Match was found ==== Run into Problem here
DocNm(i, 1).Offset(0, 1).Value = "Match"
Exit For
End If
Next j
If i > UBound(NroNm) Then
'No match was found ==== Run into Problem here
DocNm(i, 1).Offset(0, 1).Value = "Not Match"
End If
Next i
End Sub

DocNm(i, 1).Offset(0, 1).Value = "Match" has no meaning for an array. An array do not have an Offset property.
If your sheet example is real in terms of ranges size, use Ranges instead of arrays.
In order to use arrays and obtain the result you need you must use a third array. Dimension it as your first array Ubound, but I will better transform your code:
Sub Variant_Array_Question()
Dim DocNm As Variant, NroNm As Variant, arrStat As Variant
Dim i As Long, j As Long, boolFound As Boolean
Dim NroLastRow As Long, DocLastRow As Long
Dim ShStart As Worksheet
Set ShStart = ActiveSheet 'use here your sheet!!!
'Arr1
DocLastRow = ShStart.Range("Q" & Rows.Count).End(xlUp).Row
DocNm = ShStart.Range("Q6:Q" & DocLastRow).value
ReDim arrStat(1 To UBound(DocNm, 1), 1 To 1) 'arr 3
'Arr2
NroLastRow = ShStart.Range("T" & Rows.Count).End(xlUp).Row
NroNm = ShStart.Range("T6:T" & NroLastRow).value
For i = 1 To UBound(DocNm)
For j = 1 To UBound(NroNm)
If DocNm(i, 1) = NroNm(j, 1) Then
boolFound = True
arrStat(i, 1) = "Match"
Exit For
End If
Next j
If Not boolFound Then
arrStat(i, 1) = "Not Match"
End If
boolFound = False
Next i
ShStart.Range("R6").Resize(UBound(arrStat, 1), 1).value = arrStat
End Sub
Not tested, but I think it will work. If you would supply an editable example, I would test it...

Here's the code that FaneDuru helped me solve. This goes for those noobs in need like me.
Sub Variant_Array_Response()
Dim DocNm As Variant, NroNm As Variant, ResStatus As Variant
Dim i As Long, j As Long, boolFound As Boolean
Dim NroLastRow As Long, DocLastRow As Long
Dim ShStart As Worksheet
Set ShStart = ActiveSheet
'Arr1
DocLastRow = ShStart.Range("Q" & Rows.Count).End(xlUp).Row
DocNm = ShStart.Range("Q6:Q" & DocLastRow).Value
'Arr2
NroLastRow = ShStart.Range("T" & Rows.Count).End(xlUp).Row
NroNm = ShStart.Range("T6:T" & NroLastRow).Value
'Arr3
'ResStatus = ShStart.Range("Q6:Q" & DocLastRow).Offset(, 1) 'What I had
ReDim ResStatus(1 To UBound(DocNm, 1), 1 To 1) 'FaneDuru's pice
For i = 1 To UBound(DocNm)
For j = 1 To UBound(NroNm)
If DocNm(i, 1) = NroNm(j, 1) Then
boolFound = True
ResStatus(i, 1) = "Match"
Exit For
End If
Next j
If Not boolFound Then
ResStatus(i, 1) = "Not Match"
End If
boolFound = False
Next i
ShStart.Range("R6").Resize(UBound(ResStatus, 1), 1).Value = ResStatus
End Sub

Related

Check if string is in Variant and then replace Yes/No results with 1/0 respectively

giving the below code, how can I check if "outArr" value is Yes or No and replace them respectively with 1 and 0?
Sub IndexMatchFirm1()
Dim destinationWs As Worksheet
Set destinationWs = ThisWorkbook.Worksheets("Master")
Dim destinationLastRow As Long
destinationLastRow = destinationWs.Range("A" & Rows.Count).End(xlUp).Row
Dim lkpArr As Variant
lkpArr = destinationWs.Range("A5:A" & destinationLastRow).Value
With Worksheets("MyData")
Dim retval As Variant
retval = Intersect(.Range("E:E"), .UsedRange)
Dim mtch As Variant
mtch = Intersect(.Range("B:D"), .UsedRange)
End With
Dim outArr As Variant
ReDim outArr(1 To UBound(lkpArr, 1), 1 To 1)
Dim i As Long
For i = 1 To UBound(lkpArr, 1)
Dim j As Long
For j = 1 To UBound(retval, 1)
If mtch(j, 3) = "FirmA" Then
Dim v
If mtch(j, 1) = lkpArr(i, 1) Then
v = retval(j, 1)
outArr(i, 1) = IIf(v = "Yes", 1, IIf(v = "No", 0, v))
End If
'If mtch(j, 1) = lkpArr(i, 1) Then
'outArr(i, 1) = retval(j, 1)
'Exit For
'End If
End If
Next j
Next i
destinationWs.Range("L5").Resize(UBound(outArr, 1), 1).Value = outArr
End Sub
I tried in many ways but none of them seems to be working. I also would like not to use the "For each cell in myrange" approach because it slows down a lot the workbook. Any suggestion?
Thanks
Simplest fix:
Dim v
'...
'...
If mtch(j, 1) = lkpArr(i, 1) Then
v = retval(j, 1)
outArr(i, 1) = IIf(v = "Yes", 1, IIf(v="No", 0, v)
Exit For 'Edit - I forgot to add this....
End If
'...
'...

i want to get the frequency of a data in a column using vba

i tried using dictionary but it only counts the repetition but i want to know the exact frequency of all datas in a column
what ive used is
Sub countThings()
Dim ws As Worksheet
Dim lastrow As Long, x As Long
Dim items As Object
Application.ScreenUpdating = False
Set ws = ActiveSheet
lastrow = ws.Range("B" & Rows.count).End(xlUp).Row
Set items = CreateObject("Scripting.Dictionary")
For x = 2 To lastrow
If Not items.exists(ws.Range("B" & x).Value) Then
items.Add ws.Range("B" & x).Value, 1
ws.Range("C" & x).Value = items(ws.Range("B" & x).Value)
Else
items(ws.Range("B" & x).Value) = items(ws.Range("B" & x).Value) + 1
ws.Range("C" & x).Value = items(ws.Range("B" & x).Value)
End If
Next x
items.RemoveAll
End Sub
and this gives me
[1: https://i.stack.imgur.com/Mhp5g.png][1]
but what i need is
[4: https://i.stack.imgur.com/UYOFu.png][4]
I think this is what you were after. Please try it.
Sub CountThings()
Dim Ws As Worksheet
Dim Items As Object ' Scripting.Dictionary
Dim Arr As Variant ' values in column B
Dim R As Long ' loop couner: Rows
Dim Key As Variant ' loop counter: dictionary keys
Set Items = CreateObject("Scripting.Dictionary")
Set Ws = ActiveSheet ' better: define tab by name
With Ws
' reading from the sheet is slow
' therefore read all items at once
Arr = .Range(.Cells(2, "B"), .Cells(.Rows.Count, "B").End(xlUp)).Value
' this is a 1-based 2-D array, like Arr([Rows], [Column])
' where column is always 1 because there's only 1 column
End With
For R = 1 To UBound(Arr)
If Items.Exists(Trim(Arr(R, 1))) Then
Items(Trim(Arr(R, 1))) = Items(Trim(Arr(R, 1))) + 1
Else
Items.Add Trim(Arr(R, 1)), 1
End If
Next R
ReDim Arr(1 To Items.Count, 1 To 2)
R = 0
For Each Key In Items.keys
R = R + 1
Arr(R, 1) = Key
Arr(R, 2) = Items(Key)
Next Key
' specify the top left cell of the target range
Ws.Cells(2, "C").Resize(UBound(Arr, 1), UBound(Arr, 2)).Value = Arr
Set Items = Nothing
End Sub
You need not Trim the Keys if you are sure that there can't be any stray leading or trailing blanks.
Your second picture doesn't need VBA. It can be produce by this formula, entered in C2 and copied down.
=COUNTIF($B$2:$B$13,$B2)
In fact, you can even do the job of my above code without VBA. Enter this formula in G2 of your sheet as an array formula (confirmed with CTL + SHIFT + ENTER if you don't have Excel 365), and the other one in H. Then copy both formulas down.
[G2] =IFERROR(INDEX($B$2:$B$13, MATCH(0, COUNTIF($G$1:G1, $B$2:$B$13), 0)), "")
[H2] =IF($G2<>"",COUNTIF($B$2:$B$13,$G2),"")
You need to assign values to column C after you have finished counting and therefore, need another loop:
Sub countThings()
Dim ws As Worksheet
Dim lastrow As Long, x As Long
Dim items As Object
Application.ScreenUpdating = False
Set ws = ActiveSheet
lastrow = ws.Range("B" & Rows.Count).End(xlUp).Row
Set items = CreateObject("Scripting.Dictionary")
For x = 2 To lastrow
If Not items.exists(ws.Range("B" & x).Value) Then
items.Add ws.Range("B" & x).Value, 1
Else
items(ws.Range("B" & x).Value) = items(ws.Range("B" & x).Value) + 1
End If
Next x
For x = 2 To lastrow
ws.Range("C" & x).Value = items(ws.Range("B" & x).Value)
Next x
items.RemoveAll
Set items = Nothing
End Sub
A simpler way to achieve what you want is to let excel do the counting for you like this:
Sub countThings2()
Dim sDataAddress As String
With ActiveSheet
sDataAddress = "$B$2:$B$" & .Cells(Rows.Count, "B").End(xlUp).Row
With .Range(sDataAddress).Offset(0, 1)
.Formula2 = "=COUNTIF(" & sDataAddress & ",B2)"
.Value = .Value
End With
End With
End Sub
i use table and 2 functions. not simple way but works :)
Sub Fx()
Dim str_Tab() As String, str_Text As String, str_Result As String
Dim int_Counter As Integer, int_TabItemCounter As Integer, int_LastRow As Integer
Dim rng_WorkRange As Range
int_LastRow = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
Set rng_WorkRange = ActiveSheet.Range("A1:A" & int_LastRow)
For i = 1 To int_LastRow
str_Text = ActiveSheet.Range("A" & i)
If i > 1 Then
str_Result = IsInArray(str_Text, str_Tab)
If str_Result = -1 Then
int_TabItemCounter = UBound(str_Tab) - LBound(str_Tab)
ReDim str_Tab(int_TabItemCounter)
str_Tab(int_TabItemCounter) = str_Text
ActiveSheet.Range("B" & i) = CountThisItem(rng_WorkRange, str_Text)
Else
ActiveSheet.Range("B" & i) = CountThisItem(rng_WorkRange, str_Text)
End If ' If str_Result = -1
Else ' If i > 1
ReDim str_Tab(i)
str_Tab(i) = str_Text
ActiveSheet.Range("B" & i) = CountThisItem(rng_WorkRange, str_Text)
End If ' If i > 1
Next i
End Sub
function to check is text in table
Function IsInArray(stringToBeFound As String, arr As Variant) As Long
Dim i As Long
' default return value if value not found in array
IsInArray = -1
For i = LBound(arr) To UBound(arr)
If StrComp(stringToBeFound, arr(i), vbTextCompare) = 0 Then
IsInArray = i
Exit For
End If
Next i
End Function
function to count item in range
Function CountThisItem(CountingRange As Range, a As String) As Integer
Dim rng_FindRange As Range
Dim LA As String
Set rng_FindRange = CountingRange.Find(a, lookat:=xlWhole)
If Not rng_FindRange Is Nothing Then
LA = rng_FindRange.Address
CountThisItem = 1
Do
Set rng_FindRange = CountingRange.Find(a, lookat:=xlWhole, after:=rng_FindRange)
If Not rng_FindRange Is Nothing And rng_FindRange.Address <> LA Then CountThisItem = CountThisItem + 1
Loop While rng_FindRange.Address <> LA
Else
CountThisItem = 0
End If
End Function

Working through a 2D Array to correct errors and then replace cells with new data

I had a module that applied code to clean cells of unicode and replace with a standard letter from a dictionary range, I am trying to now do that by using a 2D array (for the first time) and then reprint the new corrected array back in the original cells. I am getting the type subscript out of range at Redim line, there maybe other errors further down the code I haven't got to yet (the unicode correction code works as used previously). Thanks for your help
Sub Test2DArray()
Worksheets("Sheet1").Activate
Dim arr As Variant, xstr
arr = ActiveSheet.UsedRange
Dim unicleanRWS As Variant, unicleanCLS
For unicleanRWS = LBound(arr, 1) To UBound(arr, 1)
For unicleanCLS = 1 To ActiveSheet.UsedRange.Rows.Count
'Originally the above line was Lbound(arr,2) to ubound(arr,2)
'but I altered as I read I could not preserve both dimensions
ReDim Preserve arr(1 To UBound(arr, 1))
xstr = arr(unicleanRWS, unicleanCLS)
keepchrs = Left(xstr, 0)
For I = 1 To Len(xstr)
If (Mid(xstr, I, 2)) = "\u" Then
Readcode = (Mid(xstr, I, 6))
CorrectUnicode = Replace(Readcode, "\u", "U+")
NormalLetter = Mid(Application.WorksheetFunction.VLookup(CorrectUnicode, _
Worksheets("Unicode").Range("A1:E1000"), 5, False), 2, 1)
xstr = keepchrs & Replace(xstr, (Mid(xstr, I, 6)), LCase(NormalLetter))
xstr = UCase(Left(xstr, 1)) & Mid(xstr, 2)
End If
Next I
arr(unicleanRWS, unicleanCLS) = xstr
Next unicleanCLS
Next unicleanRWS
FirstCell = arr(0, 0).Address
FirstCell.Resize(UBound(arr, 1), UBound(arr, 2)) = arr
End Sub
Clean Values in Range
Option Explicit
Sub Test2DArray()
Dim wb As Workbook
Set wb = ThisWorkbook ' The workbook containing this code.
Dim ws As Worksheet
Set ws = wb.Worksheets("Sheet1")
Dim rng As Range
Set rng = ws.UsedRange
Dim arr As Variant
arr = rng.Value
Dim xstr As Variant
Dim i As Long
Dim j As Long
Dim n As Long
Dim keepChrs As String
Dim ReadCode As String
Dim CorrectUnicode As String
Dim NormalLetter As String
For i = 1 To UBound(arr, 1)
For j = 1 To UBound(arr, 2)
xstr = arr(i, j)
keepChrs = Left(xstr, 0)
' This works well, you say.
For n = 1 To Len(xstr)
If (Mid(xstr, n, 2)) = "\u" Then
ReadCode = (Mid(xstr, n, 6))
CorrectUnicode = Replace(ReadCode, "\u", "U+")
NormalLetter = Mid(Application.WorksheetFunction.VLookup(CorrectUnicode, Worksheets("Unicode").Range("A1:E1000"), 5, False), 2, 1)
xstr = keepChrs & Replace(xstr, (Mid(xstr, n, 6)), LCase(NormalLetter))
xstr = UCase(Left(xstr, 1)) & Mid(xstr, 2)
End If
Next n
arr(i, j) = xstr
Next j
Next i
rng.Value = arr
End Sub
Getting your data from a Range into a memory-based array is more straightforward than you're thinking. In your situation, I believe
Dim arr As Variant
arr = ActiveSheet.UsedRange.Value
is all that's required. There is no need for a Redim at all. Alternatively, consider that UsedRange can sometimes give different results. So this example is more of a guarantee to get exactly what you want:
Dim arr As Variant
Dim lastRow As Long
Dim lastCol As Long
With ActiveSheet
lastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
lastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
Dim dataRange As Range
Set dataRange = .Range("A1").Resize(lastRow, lastCol)
arr = dataRange.Value
End With
Now, everytime you need to determine the size of the array, you should use the UBound and LBound functions.
VBasic2008's answer worked perfectly for a small set of data but because I had a large amount of data I ended up adding some extra code to break my used range into sections so I have noted the final code below in case anyone else has a large dataset. This took 210 seconds to cleanup 240m cells.
I added a timer as well, and a timed message to avoid a "Not responding" occurence I sometimes get with large data, both are obviously optional but I've included everything in case it is helpful:
Private Function MsgTimed(Message As String, Optional Seconds As Integer = 5, _
Optional Title As String = "", Optional Options As Integer = 0)
' Displays a message box for a predetermined duration then auto closes it.
' Uses the same syntax as the built-in Popup function referenced on the page below...
' http://msdn.microsoft.com/en-us/library/x83z1d9f%28v=vs.84%29.aspx
CreateObject("WScript.Shell").Run "mshta.exe vbscript:close(CreateObject(""WScript.Shell"")" _
& ".Popup(""" & Message & """," & Seconds & ",""" & Title & """," & Options & "))"
End Function
---------------
Sub TestArray()
Dim StartTime As Double
Dim SecondsElapsed As Double
StartTime = Timer
Dim wb As Workbook
Set wb = ThisWorkbook ' The workbook containing this code.
Dim ws As Worksheet
Set ws = wb.Worksheets("Sheet1")
' Look up the usedrange and then break into 10 sections due to size
Dim rng As Range, rng2, srng
Set rng = ws.UsedRange
Dim SectionsRng As Integer
Dim SectionStart As Long, SectionEnd
Dim MaxCol As String
Dim arr As Variant
Dim xstr As Variant
Dim i As Long
Dim j As Long
Dim n As Long
Dim keepChrs As String
Dim ReadCode As String
Dim CorrectUnicode As String
Dim NormalLetter As String
' Create 50 sections of UsedRange to avoid Out of Memory error
SectionStart = rng.Cells.Row
SectionEnd = Round(rng.rows.Count / 50)
MaxCol = Split(Cells(1, rng.Columns.Count).Address, "$")(1)
For SectionsRng = 1 To 50
If SectionsRng > 1 Then SectionStart = 1 + SectionEnd
If SectionsRng > 1 Then SectionEnd = Round(SectionEnd / (SectionsRng - 1) * SectionsRng)
srng = ("$A$" & SectionStart & ":$" & MaxCol & "$" & SectionEnd)
Set rng2 = ws.Range(srng)
Debug.Print rng2.Address
' Create array and process data
arr = rng2.Value
For i = 1 To UBound(arr, 1)
For j = 1 To UBound(arr, 2)
xstr = arr(i, j)
keepChrs = Left(xstr, 0)
For n = 1 To Len(xstr)
If (Mid(xstr, n, 2)) = "\u" Then
ReadCode = (Mid(xstr, n, 6))
CorrectUnicode = Replace(ReadCode, "\u", "U+")
NormalLetter = Mid(Application.WorksheetFunction.VLookup(CorrectUnicode, Worksheets("Unicode").Range("A1:E1000"), 5, False), 2, 1)
xstr = keepChrs & Replace(xstr, (Mid(xstr, n, 6)), LCase(NormalLetter))
xstr = UCase(Left(xstr, 1)) & Mid(xstr, 2)
End If
Next n
arr(i, j) = xstr
Next j
Next i
rng2.Value = arr
' MessageBox seems to stop Not responding occuring
SecondsElapsed = Round(Timer - StartTime, 2)
MsgTimed "Time " & SecondsElapsed & " Reached Row: " & SectionEnd, 3, "Alert", vbInformation
Next SectionsRng
'Print Timer in Immediate Window
Debug.Print SecondsElapsed
End Sub

Grouping two columns to shrink row count by comparing | code optimization

I try to find a vba solution for the following problem:
I have two columns and try to group column1 in a comma separate way to have less rows.
e.g.
example:
I tried this, and it worked - but It take too long (about 300.000 Rows). Is there any better solution that task?
*Its just one part of my macro
For Each r In fr
If st = "" Then
st = Application.WorksheetFunction.Clean(Trim(ws.Cells(r.row, "L").Value))
Else
If Not IsInArray(Split(st, ","), ws.Cells(r.row, "L").Value) Then
st = st & ", " & Application.WorksheetFunction.Clean(Trim(ws.Cells(r.row, "L").Value))
End If
End If
If usrCheck = True Then
If str = "" Then
str = Application.WorksheetFunction.Clean(Trim(ws.Cells(r.row, "A").Value))
Else
If Not IsInArray(Split(str, ","), ws.Cells(r.row, "A").Value) Then
str = str & ", " & Application.WorksheetFunction.Clean(Trim(ws.Cells(r.row, "A").Value))
End If
End If
End If
Next
Maybe using Dictionary would be fast. What about:
Sub Test()
Dim x As Long, lr As Long, arr As Variant
Dim dict1 As Object: Set dict1 = CreateObject("Scripting.Dictionary")
Dim dict2 As Object: Set dict2 = CreateObject("Scripting.Dictionary")
With Sheet1 'Change accordingly
'Return your last row from column A
lr = .Cells(.Rows.Count, 1).End(xlUp).Row
'Get array and loop through it
arr = .Range("A2:B" & lr).Value
For x = LBound(arr) To UBound(arr)
dict1(arr(x, 2)) = arr(x, 2)
Next
'Loop through dictionary filling a second one
For Each Key In dict1.keys
For x = LBound(arr) To UBound(arr)
If arr(x, 2) = Key Then dict2(arr(x, 1)) = arr(x, 1)
Next x
.Range("F" & .Cells(.Rows.Count, 6).End(xlUp).Row + 1) = Key
.Range("G" & .Cells(.Rows.Count, 7).End(xlUp).Row + 1) = Join(dict2.Items, ", ")
dict2.RemoveAll
Next
End With
End Sub
This will get you all unique items from column A though, so if there can be duplicates and you want to keep them, this is not for you =)
Try also this, please. It works only in memory and on my computer takes less then 3 seconds for 300000 rows. The range must be filtered, like in your picture. If not, the filtering can also be easily automated.
Private Sub CondensData()
Dim sh As Worksheet, arrInit As Variant, arrIn As Variant, i As Long
Dim arrFinal() As Variant, lastRow As Long, Nr As Long, El As Variant
Dim strTemp As String, k As Long
Set sh = ActiveSheet
lastRow = sh.Cells(sh.Rows.count, "A").End(xlUp).Row
arrIn = sh.Range("B2:B" & lastRow + 1).Value
'Determine the number of the same accurrences:
For Each El In arrIn
i = i + 1
If i >= 2 Then
If arrIn(i, 1) <> arrIn(i - 1, 1) Then Nr = Nr + 1
End If
Next
ReDim arrFinal(Nr, 1)
arrInit = sh.Range("A2:B" & lastRow).Value
For i = 2 To UBound(arrInit, 1)
If i = 1 Then
strTemp = arrInit(1, 1)
Else
If arrInit(i, 2) = arrInit(i - 1, 2) Then
If strTemp = "" Then
strTemp = arrInit(i, 1)
Else
strTemp = strTemp & ", " & arrInit(i, 1)
End If
Else
arrFinal(k, 0) = arrInit(i - 1, 2)
arrFinal(k, 1) = strTemp
k = k + 1: strTemp = ""
End If
End If
Next i
sh.Range("C2:D" & lastRow).Clear
sh.Range("C2:D" & k - 1).Value = arrFinal
sh.Range("C:D").EntireColumn.AutoFit
MsgBox "Solved..."
End Sub
It will return the result in columns C:D

Excel VBA If Then Loop conditions

I've been struggling with this for a few days. Any help would greatly be appreciated!
It's difficult to explain, so I'll do my best.
What I'm trying to do is count the number of results each query has and then categorize them based on that result count.
For example if Query_A has 1 exact result and then Query_Z has 1 exact result then that would be a total of 2 queries that have 1 result.
I'm currently trying to use Loop with if then statements, but I'm at a loss.
Here is some example data and the output I was hoping for: Query_Example_Data_and_Results.xlsx - This is not my real spreadsheet as it is thousands of rows of data and a very large file size.
The code below does pull the query count (removing the query dupes), but does not give the query result count.. I would have provide my code attempts, but I know I'm not even close... So I have removed my failed attempts hoping I'm being clear enough to get steered in the right direction.
Sub Query_Count()
G_40 = 0
Query = ""
Application.StatusBar = " ~~ ~~ QUERY COUNT ~~ RUNNING ~~ ~~ " & x
x = 2
Do Until Sheets(1).Cells(x, 1) = ""
If Sheets(1).Cells(x, 9) = "Yes" Then
If Query <> Sheets(1).Cells(x, 1) Then
G_40 = G_40 + 1
End If
End If
Query = Sheets(1).Cells(x, 1)
x = x + 1
Loop
Application.StatusBar = "DONE RUNNING QUERY COUNT OF " & x & " ROWS!"
G = 40
Sheets(3).Cells(G, 7) = G_40 'query_count:
End Sub
Thank you in advance!
Based on your Example this code will do the job:
Option Explicit
Sub getResults()
Application.ScreenUpdating = False
Dim ws1 As Worksheet, ws2 As Worksheet, lr&
Set ws1 = ThisWorkbook.Sheets("Example_Query_Data")
Set ws2 = ThisWorkbook.Sheets("Example_Results")
lr = ws1.Range("A" & Rows.count).End(xlUp).Row
Dim arr() As String, i&, j&, cnt&
Dim varr() As String
cnt = 0
ReDim arr(lr - 2)
For i = 2 To lr
arr(i - 2) = CStr(ws1.Range("A" & i).Value) ' fill array
Next i
Call RemoveDuplicate(arr) 'remove duplicate
ReDim varr(0 To UBound(arr), 0 To 1)
For i = LBound(arr) To UBound(arr)
varr(i, 0) = arr(i)
varr(i, 1) = getCount(arr(i), ws1, j, lr)
Next i
Call PrepTable(ws2)
Call UpdateTable(ws2, ws1, varr, j, lr) ' Update table
Application.ScreenUpdating = True
End Sub
Function getCount(qName$, ByRef ws1 As Worksheet, ByRef i&, lr&)
Dim count&
count = 0
For i = 2 To lr
If (StrComp(CStr(ws1.Range("A" & i).Value), qName, vbTextCompare) = 0) And _
(StrComp(CStr(ws1.Range("C" & i).Value), "Yes", vbTextCompare) = 0) Then count = count + 1
Next i
getCount = count ' return count
End Function
Sub UpdateTable(ByRef ws As Worksheet, ByRef ws2, ByRef arr() As String, ByRef i&, lr&)
Dim tblIter&
For tblIter = 2 To 12
For i = LBound(arr) To UBound(arr)
If arr(i, 1) = tblIter - 1 Then
ws.Range("B" & tblIter).Value = ws.Range("B" & tblIter).Value + 1
End If
Next i
Next tblIter
Call ElevenAndMore(ws, ws2, arr, lr, i)
End Sub
Sub PrepTable(ws As Worksheet)
ws.Range("B2:B12").ClearContents
End Sub
Sub ElevenAndMore(ByRef ws As Worksheet, ByRef ws2, ByRef arr() As String, lr&, ByRef i)
Dim cnt&, j&
cnt = 0
For i = LBound(arr) To UBound(arr)
For j = 1 To lr
If StrComp(CStr(ws2.Range("A" & j).Value), arr(i, 0), vbTextCompare) = 0 Then
cnt = cnt + 1
End If
Next j
If cnt > 10 Then ws.Range("B12").Value = ws.Range("B12").Value + 1
cnt = 0
Next i
End Sub
Sub RemoveDuplicate(ByRef StringArray() As String)
Dim lowBound$, UpBound&, A&, B&, cur&, tempArray() As String
If (Not StringArray) = True Then Exit Sub ' is empty?
lowBound = LBound(StringArray)
UpBound = UBound(StringArray)
ReDim tempArray(lowBound To UpBound)
cur = lowBound ' first item
tempArray(cur) = StringArray(lowBound)
For A = lowBound + 1 To UpBound
For B = lowBound To cur
If LenB(tempArray(B)) = LenB(StringArray(A)) Then
If InStrB(1, StringArray(A), tempArray(B), vbBinaryCompare) = 1 Then Exit For
End If
Next B
If B > cur Then cur = B: tempArray(cur) = StringArray(A)
Next A
ReDim Preserve tempArray(lowBound To cur) ' reSize
StringArray = tempArray ' copy
End Sub
Post-Comment Edit:
Change these three:
Add +28 to the tblIter
Sub UpdateTable(ByRef ws As Worksheet, ByRef ws2, ByRef arr() As String, ByRef i&, lr&)
Dim tblIter&
For tblIter = 2 To 12
For i = LBound(arr) To UBound(arr)
If arr(i, 1) = tblIter - 1 Then
ws.Range("B" & tblIter + 28).Value = ws.Range("B" & tblIter + 28).Value + 1
End If
Next i
Next tblIter
Call ElevenAndMore(ws, ws2, arr, lr, i)
End Sub
Simply change location to B40
Sub ElevenAndMore(ByRef ws As Worksheet, ByRef ws2, ByRef arr() As String, lr&, ByRef i)
Dim cnt&, j&
cnt = 0
For i = LBound(arr) To UBound(arr)
For j = 1 To lr
If StrComp(CStr(ws2.Range("A" & j).Value), arr(i, 0), vbTextCompare) = 0 Then
cnt = cnt + 1
End If
Next j
If cnt > 10 Then ws.Range("B40").Value = ws.Range("B40").Value + 1
cnt = 0
Next i
End Sub
And prep table change range
Sub PrepTable(ws As Worksheet)
ws.Range("B30:B40").ClearContents
End Sub
and this should do!

Resources