duplicate rows based on value - excel

I have a code which goes trough a big database and checks for first 2 letters , if they answer a certain term they are getting replaced with certain integer ...
i want to duplicate the row which has "RE" as string in the first 2 letters and replace the "RE" to "821" and the duplicated row to "841"
Here is the code i have now..
Sub Swap()
Dim i As Long, N As Long, v As Variant, frst As String
Call deletes
Application.ScreenUpdating = False
N = Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To N
v = Cells(i, "A").Value
If Len(v) >= 2 Then
frst = Left(v, 2)
If frst = "RE" Then
Cells(i, "A").Value = Replace(v, "RE", "821")
ElseIf frst = "NI" Then
Cells(i, "A").Value = Replace(v, "NI", "801")
ElseIf frst = "NF" Then
Cells(i, "A").Value = Replace(v, "NF", "831")
ElseIf frst = "NV" Then
Cells(i, "A").Value = Replace(v, "NV", "571")
End If
End If
Next i
End Sub

Multiple Replacements
The code is written in this way to allow different lengths of the strings to be searched for (Lens - Lengths Array). It is understood that the replacements can be of any 'allowed' length.
Adjust the values in the constants section. Also, rather qualify the range and its worksheet e.g.:
With ThisWorkbook.Worksheets("Sheet1").Range(FirstCellAddress)
The Code
Option Explicit
Sub Swap()
Const FirstCellAddress As String = "A2"
Const SrcList As String = "RE,NI,NF,NV"
Const FstList As String = "821,801,831,571"
Const SndList As String = "841,811,851,591"
' Define range.
Dim rg As Range
With Range(FirstCellAddress)
Set rg = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If rg Is Nothing Then Exit Sub
Set rg = .Resize(rg.Row - .Row + 1)
End With
' Write values from range to Data Array.
Dim rCount As Long: rCount = rg.Rows.Count
Dim Data As Variant
If rCount > 1 Then
Data = rg.Value
Else
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = rg.Value
End If
' Write lists to arrays.
Dim Src() As String: Src = Split(SrcList, ",")
Dim Fst() As String: Fst = Split(FstList, ",")
Dim Snd() As String: Snd = Split(SndList, ",")
' Write lenghts of values in Search Array to Lengths Array.
Dim sUpper As Long: sUpper = UBound(Src)
Dim n As Long
Dim Lens() As Long: ReDim Lens(0 To sUpper)
For n = 0 To sUpper
Lens(n) = Len(Src(n))
Next n
' Define Unique Dictionary.
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare ' '1' is used in 'StrComp' and 'Replace'.
Dim i As Long
Dim cValue As Variant
' Modify (replace) values in Data Array (using Unique Dictionary,
' test if first or second replacement is to be used).
For i = 1 To rCount
cValue = Data(i, 1)
If Not IsError(cValue) Then
For n = 0 To sUpper
If StrComp(Left(cValue, Lens(n)), Src(n), 1) = 0 Then
If dict.Exists(cValue) Then
Data(i, 1) = Replace(cValue, Src(n), Snd(n), , 1, 1)
Else
dict.Add cValue, Empty
Data(i, 1) = Replace(cValue, Src(n), Fst(n), , 1, 1)
End If
Exit For
End If
Next n
Else ' error value
End If
Next i
Set dict = Nothing
' Write modified values from Data Array to range.
rg.Value = Data
End Sub

Related

How to iterate through a datadump and paste unique values into two separate tables [VBA]

I currently have two spreadsheets: one that pulls data from a SQL Server and is a data dump and one that needs to have those values populated into them. For the sake of simplicity, I've compiled a mini prototype to use for the purpose of my question. Things to note, the data dump sheet will have a varying amount of rows, however the columns will be static which should hopefully make for easy mapping. What I need my macro to be able to accomplish is to
Check if an ID value matches the one directly below it, if so
Check if the Spouse_Indicator field has an "N" or "Y" value
If the indicator is an "N" value then I need the corresponding rows from the employer and title fields to be populated into the student table
If the indicator is a "Y" value then I need the corresponding rows from the employer and title fields to be populated into the spouse table
If there is a sequence where the ID does not match the one directly below it, the data automatically gets populated into the student table
The problem that I am having with the way that my macro is set up is that only the most recent ID with a "N" indicator is getting populated into every cell of the student table whereas I need only unique values to be populated until the last ID has been read. The image attached shows a small sample size of the data, the first table shows what my macro is producing while the last table shows my target. I am also including my code to show what I've gotten so far. Let me know if I need to clarify anything, thanks a bunch.
Sub test2()
Dim wb As Workbook
Dim ws As Worksheet
Dim id As Range
Dim cell As Range
Dim student_employer As Range
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
Set id = ws.Range("A2:A" & Cells(Rows.Count, "A").End(xlUp).Row)
Set student_employer = ws.Range("G3:G8")
For Each cell In id
If cell.Value = cell.Offset(1, 0).Value And cell.Offset(0, 1).Value = "N" Then
cell.Offset(0, 2).Copy student_employer.Cells
End If
Next
MsgBox ("DONE")
End Sub
I've edited my code and it is somewhat capturing what I am trying to accomplish, however I need the values to be pasted into the next empty cell, while mine currently skips the amount of cells depending on when the next copy-paste takes place.
Sub test2()
Dim id As Long
Dim x As Long
Dim emp As Range
Set emp = Range("G3:G8")
id = Cells(Rows.Count, "A").End(xlUp).Row
For x = 2 To id
If Cells(x, 1).Value = Cells(x, 1).Offset(1, 0) Then
Cells(x, 1).Offset(0, 2).Copy Cells(x, 6).Offset(1, 0)
End If
Next x
MsgBox ("DONE")
End Sub
Copy Unique Rows
Adjust the values in the constants section. If you feel like it, use the out-commented constants and sCols to get rid of the 'magic' numbers (1, 2, 3, 4).
For the sake of simplicity, it is assumed that the source data starts in cell A1 (CurrentRegion).
Option Explicit
Sub test1()
Const sName As String = "Sheet1"
'Const sCritCol As Long = 2
'Const sColsList As String = "1,3,4"
'Const scCount As Long = 4
Const sCrit1 As String = "N"
Const sCrit2 As String = "Y"
Const dName As String = "Sheet1"
Const dFirst As String = "F1"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim srg As Range: Set srg = sws.Range("A1").CurrentRegion
If srg.Columns.Count <> 4 Then Exit Sub
Dim srCount As Long: srCount = srg.Rows.Count
If srCount = 1 Then Exit Sub
Dim sData As Variant: sData = srg.Value
'Dim sCols() As String: sCols = Split(sColsList, ",")
Dim dict1 As Object: Set dict1 = CreateObject("Scripting.Dictionary")
dict1.CompareMode = vbTextCompare
Dim dict2 As Object: Set dict2 = CreateObject("Scripting.Dictionary")
dict2.CompareMode = vbTextCompare
Dim cDat As Variant: ReDim cDat(1 To 3)
Dim Key As Variant
Dim sCrit As Variant
Dim r As Long
For r = 2 To srCount
sCrit = sData(r, 2)
Select Case UCase(CStr(sCrit))
Case sCrit1
Key = sData(r, 1)
If Not dict1.Exists(Key) Then
cDat(1) = sData(r, 1)
cDat(2) = sData(r, 3)
cDat(3) = sData(r, 4)
dict1(Key) = cDat
End If
Case sCrit2
Key = sData(r, 1)
If Not dict2.Exists(Key) Then
cDat(1) = sData(r, 1)
cDat(2) = sData(r, 3)
cDat(3) = sData(r, 4)
dict2(Key) = cDat
End If
End Select
Next r
Dim drCount As Long: drCount = dict1.Count + dict2.Count + 4
Dim dData As Variant: ReDim dData(1 To drCount, 1 To 3)
r = 1
dData(r, 1) = "student"
r = r + 1
dData(r, 1) = sData(1, 1)
dData(r, 2) = sData(1, 3)
dData(r, 3) = sData(1, 4)
Dim n As Long
If dict1.Count > 0 Then
For Each Key In dict1.Keys
r = r + 1
For n = 1 To 3
dData(r, n) = dict1(Key)(n)
Next n
Next Key
End If
r = r + 1
dData(r, 1) = "spouse"
r = r + 1
dData(r, 1) = sData(1, 1)
dData(r, 2) = sData(1, 3)
dData(r, 3) = sData(1, 4)
If dict2.Count > 0 Then
For Each Key In dict2.Keys
r = r + 1
For n = 1 To 3
dData(r, n) = dict2(Key)(n)
Next n
Next Key
End If
Application.ScreenUpdating = False
' Write.
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim drg As Range: Set drg = dws.Range(dFirst).Resize(r, 3)
drg.Clear ' because of merged cells
drg.Value = dData
' Clear below.
Dim crg As Range
Set crg = drg.Resize(dws.Rows.Count - drg.Row - r + 1).Offset(r)
crg.Clear
' Format 'student'
With drg.Rows(1)
.Cells(1).Font.Bold = True
.MergeCells = True
.HorizontalAlignment = xlCenter
.BorderAround xlContinuous, xlThick
End With
' Format 'spouse'.
With drg.Rows(dict1.Count + 3)
.Cells(1).Font.Bold = True
.MergeCells = True
.HorizontalAlignment = xlCenter
.BorderAround xlContinuous, xlThick
End With
' Format all.
drg.EntireColumn.AutoFit
Application.ScreenUpdating = True
MsgBox ("DONE")
End Sub

How to count the number of unique strings separated by a space in each cell?

I have strings of numbers in one column, each cell contains from 1 to n sequences separated by a space e.g.
1001
2034 2034 2034
3456 3456 3456
is there a way to count how many unique sequences exist in each cell and place this number in the adjacent cell?
So e.g.
Column 1 Column 2
1001 1
2034 2034 2034 1
3456 3456 3456 1
3455 3455 5674 2
1234 3456 3456 4568 6754 4
So, I have managed to get to this point but how do I go about the range and the loop to basically print the result to each cell (to the right) of the analysed range?
Sub CountStuff()
Dim c As Collection
Set c = New Collection
ary = Split(ActiveCell.Value, " ")
On Error Resume Next
For Each a In ary
c.Add a, CStr(a)
Next a
On Error GoTo 0
Debug.Print c.Count
End Sub
Following from my comment above:
Sub CountStuff()
Dim col As Collection, c As Range, arr, v, rng As Range
Set rng = ActiveSheet.Range("A2:A100") 'for example
For Each c In rng.Cells
If Len(c.Value) > 0 Then
arr = Split(c.Value, " ")
Set col = New Collection
For Each v In arr
If Len(v) > 0 Then
On Error Resume Next 'ignore error on duplicate key
col.Add v, CStr(v)
On Error GoTo 0
End If
Next v
c.Offset(0, 1).Value = col.Count 'put count one cell over
End If
Next c
End Sub
Count Unique Substrings (UDF)
The Function
Option Explicit
Function CountUniqueSubStrings( _
ByVal SplitString As String, _
Optional ByVal Delimiter As String = " ") _
As Long
Dim SubStrings() As String: SubStrings = Split(SplitString, Delimiter)
Dim ssCount As Long: ssCount = UBound(SubStrings)
Dim usCount As Long
If ssCount < 1 Then
usCount = ssCount + 1
Else
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Dim cString As String
Dim n As Long
For n = 0 To ssCount
cString = SubStrings(n)
If Len(cString) > 0 Then
dict(SubStrings(n)) = Empty
End If
Next n
usCount = dict.Count
End If
CountUniqueSubStrings = usCount
End Function
Excel Example
=CountUniqueSubStrings(A1)
VBA Example
Sub CountUniqueSubStringsTEST()
' Define constants.
Const sFirst As String = "A2"
Const dFirst As String = "B2"
Const Delimiter As String = " "
' Create a reference to the worksheet.
Dim ws As Worksheet: Set ws = ActiveSheet
' Maybe better examples:
'Set ws = Sheet1
'Set ws = ThisWorkbook.Worksheets("Sheet1")
' Create a reference to the Source Column Range.
Dim srg As Range
Dim rCount As Long
With ws.Range(sFirst)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If fCell Is Nothing Then Exit Sub
rCount = lCell.Row - .Row + 1
Set srg = .Resize(rCount)
Debug.Print srg.Address
End With
' Write values from the Source Column Range to the Data Array.
Dim Data As Variant
If rCount = 1 Then ' one cell only
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = srg.Value
Else
Data = srg.Value
End If
' Replace the values in the Data Array with the 'unique counts'.
Dim r As Long
For r = 1 To rCount
Data(r, 1) = CountUniqueSubStrings(Data(r, 1), Delimiter)
Next r
' Create a reference to the Destination Column Range.
Dim drg As Range: Set drg = ws.Range(dFirst).Resize(rCount)
' Write the 'unique counts' from the Data Array
' to the Destination Column Range.
drg.Value = Data
' Clear the contents below the Destination Column Range.
With drg.Cells(1)
.Resize(.Worksheet.Rows.Count - .Row - rCount + 1) _
.Offset(rCount).ClearContents
End With
End Sub

Copy and paste values into one cell

I want to create a VBA code where it could copy all the unique file owner emails into one cell and all the file locations into the cell next to it, being separated by a comma. Is that possible? I created a code to grab the unique values and pasted into cell L1 and create a table, and this is what I have so far:
This is an example of what Excel would look like
This is an example what I want the VBA code to do
Public Sub unique_emails()
Columns("B:B").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("L1" _
), Unique:=True
Range("L1").Select
Dim tbl As ListObject
Dim rng As Range
Set rng = Range(Range("L1"), Range("L1").SpecialCells(xlLastCell))
Set tbl = ActiveSheet.ListObjects.Add(xlSrcRange, rng, , xlYes)
tbl.TableStyle = "TableStyleMedium16"
End Sub
Unique Delimited (Dictionary)
Adjust the values in the constants section.
Option Explicit
Public Sub unique_emails()
Const sFirst As String = "A1"
Const dFirst As String = "L1"
Const Delimiter As String = ", "
' Worksheet
Dim ws As Worksheet: Set ws = ActiveSheet
' Source Range
Dim rg As Range
With ws.Range(sFirst).Resize(, 2)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , xlByRows, xlPrevious)
If lCell Is Nothing Then Exit Sub
Set rg = .Resize(lCell.Row - .Row + 1)
End With
Dim rCount As Long: rCount = rg.Rows.Count
' Source Range to Array
Dim Data As Variant: Data = rg.Value
Dim n As Long
If rCount > 1 Then
' Array to Dictionary
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim Key As Variant
For n = 2 To rCount
Key = Data(n, 2)
If Not IsError(Key) Then
If Len(Key) > 0 Then
If dict.Exists(Key) Then
dict(Key) = dict(Key) & Delimiter & Data(n, 1)
Else
dict(Key) = Data(n, 1)
End If
End If
End If
Next n
' Dictionary to Array
n = 1
For Each Key In dict.Keys
n = n + 1
Data(n, 1) = Key
Data(n, 2) = dict(Key)
Next Key
Else
n = 1
End If
' Switch Headers
Key = Data(1, 1): Data(1, 1) = Data(1, 2): Data(1, 2) = Key
' Array to Destination Range
With ws.Range(dFirst).Resize(, 2)
.Resize(n).Value = Data
.Resize(.Worksheet.Rows.Count - .Row - n + 1).Offset(n).ClearContents
End With
End Sub

Sum rows based on cell value and then delete all duplicates

I have an Excel Sheet where some rows may contain the same data as other rows. I need a macro to sum all the values in that column and delete all the duplicates rows, except for the first one, which contains the sum of the rest.
I have tried multiple versions of code and the code that produces the results closest to what I need looks like this, but this code contains one problem is: infinite loop.
Sub delet()
Dim b As Integer
Dim y As Worksheet
Dim j As Double
Dim k As Double
Set y = ThisWorkbook.Worksheets("Sheet1")
b = y.Cells(Rows.Count, 2).End(xlUp).Row
For j = 1 To b
For k = j + 1 To b
If Cells(j, 2).Value = Cells(k, 2).Value Then
Cells(j, 3).Value = (Cells(j, 3).Value + Cells(k, 3).Value)
Rows(k).EntireRow.Delete
k = k - 1
ElseIf Cells(j, 2).Value <> Cells(k, 2).Value Then
k = k
End If
Next
Next
End Sub
I would recommend getting the data in an array and then do the relevant operation. This is a small range and it may not affect the performance but for a larger dataset it will matter.
Is this what you are trying?
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, i As Long, j As Long
Dim MyAr As Variant, outputAr As Variant
Dim col As New Collection
Dim itm As Variant
Dim totQty As Double
'~~> Change this to the relevant sheet
Set ws = Sheet1
With ws
'~~> Find last row of col A
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Get those value in an array
MyAr = .Range("A2:C" & lRow).Value2
'~~> Get unique collection of Fam.
For i = LBound(MyAr) To UBound(MyAr)
If Len(Trim(MyAr(i, 2))) <> 0 Then
On Error Resume Next
col.Add MyAr(i, 2), CStr(MyAr(i, 2))
On Error GoTo 0
End If
Next i
'~~> Prepare array for output
ReDim outputAr(1 To col.Count, 1 To 3)
i = 1
For Each itm In col
'~~> Get Product
For j = LBound(MyAr) To UBound(MyAr)
If MyAr(i, 2) = itm Then
outputAr(i, 1) = MyAr(i, 1)
Exit For
End If
Next j
'~~> Fam.
outputAr(i, 2) = itm
totQty = 0
'~~> Qty
For j = LBound(MyAr) To UBound(MyAr)
If MyAr(j, 2) = itm Then
totQty = totQty + Val(MyAr(j, 3))
End If
Next j
outputAr(i, 3) = totQty
i = i + 1
Next itm
'~~> Copy headers
.Range("A1:C1").Copy .Range("G1")
'~~> Write array to relevant range
.Range("G2").Resize(UBound(outputAr), 3).Value = outputAr
End With
End Sub
Output
If VBA isn't essential and you've got 365:
In cell G2 enter the formula =UNIQUE(A2:B11)
In cell I2 enter the formula =SUMIFS(C2:C11,A2:A11,INDEX(G2#,,1),B2:B11,INDEX(G2#,,2))
Remove Duplicates with Sum
Adjust the values in the constants section.
Note that if you choose the same worksheets and "A1", you will overwrite.
The Code
Option Explicit
Sub removeDupesSum()
Const sName As String = "Sheet1"
Const dName As String = "Sheet1"
Const dFirst As String = "G1"
Dim wb As Workbook: Set wb = ThisWorkbook
' Write values from Source Range to Data Array.
Dim Data As Variant
Data = wb.Worksheets(sName).Cells(1).CurrentRegion.Value
' Write unique values from Data Array to Unique Sum Dictionary.
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
Dim arr As Variant: ReDim arr(2 To UBound(Data, 1)) ' for first column
Dim n As Long: n = 1
Dim i As Long
For i = 2 To UBound(Data, 1)
If dict.Exists(Data(i, 2)) Then
dict(Data(i, 2)) = dict(Data(i, 2)) + Data(i, 3)
Else
n = n + 1
arr(n) = Data(i, 1)
dict(Data(i, 2)) = Data(i, 3)
End If
Next i
Dim Result As Variant: ReDim Result(1 To dict.Count + 1, 1 To 3)
' Write headers.
For i = 1 To 3
Result(1, i) = Data(1, i)
Next i
Erase Data
' Write 'body'.
Dim Key As Variant
i = 1
For Each Key In dict.Keys
i = i + 1
Result(i, 1) = arr(i)
Result(i, 2) = Key
Result(i, 3) = dict(Key)
Next Key
' Write values from Result Array to Destination Range.
With wb.Worksheets(dName).Range(dFirst).Resize(, 3)
.Resize(i).Value = Result
.Resize(.Worksheet.Rows.Count - .Row - i + 1).Offset(i).ClearContents
End With
End Sub

VBA: Nested Loops and Knowing How Many Times it's Looped

Dim pos As Range, range1 As Range, range2 As Range
Dim x As Variant, Y As Variant
Set pos = Sheets("Sheet1").Cells(5, 6)
For Each y In range1
Set pos = pos.Offset(3, 0) 'Currently setting 3 spaces between each change of Y
For Each x In range2
If y = x Then
x.Cells(, 5).Copy pos
Set pos = pos.Offset(1, 0)
End If
Next x
Next y
Instead of putting spaces of 3, I want to know how many times X is copied for each time that Y changes, how would you do this?
I was thinking a counter, but how would you reset it?
Counting Using an Array or a Dictionary
All solutions are case-insensitive, i.e. A=a.
These are 3 pairs of solutions where each first is using a second loop, while each second is using Application.CountIf as a more efficient way instead.
The second pair (solutions 3 and 4) should be the most efficient, but can only be used if the values in range1 are unique, while the others can be used in any case, the first pair (solutions 1 and 2) probably being more efficient.
Also consider the differences between retrieving the values from the array and retrieving the values from the dictionary.
The Code
Option Explicit
Sub testUniqueDictionaryLoop()
Dim range1 As Range: Set range1 = Range("D2:D11")
Dim range2 As Range: Set range2 = Range("F2:H11")
Dim y As Range
Dim x As Range
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
For Each y In range1.Cells
If Not dict.Exists(y.Value) Then
dict(y.Value) = 0
For Each x In range2.Cells
If StrComp(x.Value, y.Value, vbTextCompare) = 0 Then
dict(y.Value) = dict(y.Value) + 1
End If
Next x
End If
Next y
' Write to the Immediate window.
Dim Key As Variant
For Each Key In dict.keys
Debug.Print Key, dict(Key)
Next Key
' Write to a two-column range.
With Range("A2").Resize(, 2)
.Resize(Rows.Count - .Row + 1).ClearContents
.Columns(1).Resize(dict.Count).Value = Application.Transpose(dict.keys)
.Columns(2).Resize(dict.Count).Value = Application.Transpose(dict.Items)
End With
End Sub
Sub testUniqueDictionaryCountIf()
Dim range1 As Range: Set range1 = Range("D2:D11")
Dim range2 As Range: Set range2 = Range("F2:H11")
Dim y As Range
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
For Each y In range1.Cells
If Not dict.Exists(y.Value) Then
dict(y.Value) = Application.CountIf(range2, y.Value)
End If
Next y
' Write to the Immediate window.
Dim Key As Variant
For Each Key In dict.keys
Debug.Print Key, dict(Key)
Next Key
' Write to a two-column range.
With Range("A2").Resize(, 2)
.Resize(Rows.Count - .Row + 1).ClearContents
.Columns(1).Resize(dict.Count).Value = Application.Transpose(dict.keys)
.Columns(2).Resize(dict.Count).Value = Application.Transpose(dict.Items)
End With
End Sub
Sub testArrayLoop()
Dim range1 As Range: Set range1 = Range("D2:D11")
Dim range2 As Range: Set range2 = Range("F2:H11")
Dim y As Range
Dim x As Range
Dim Data As Variant: ReDim Data(1 To range1.Cells.CountLarge, 1 To 2)
Dim i As Long
For Each y In range1.Cells
i = i + 1
Data(i, 1) = y.Value
Data(i, 2) = 0
For Each x In range2.Cells
If StrComp(x.Value, y.Value, vbTextCompare) = 0 Then
Data(i, 2) = Data(i, 2) + 1
End If
Next x
Next y
' Write to the Immediate window.
For i = 1 To UBound(Data, 1)
Debug.Print Data(i, 1), Data(i, 2)
Next i
' Write to a two-column range.
With Range("A2").Resize(, 2)
.Resize(Rows.Count - .Row + 1).ClearContents
.Resize(UBound(Data, 1)).Value = Data
End With
End Sub
Sub testArrayCountIf()
Dim range1 As Range: Set range1 = Range("D2:D11")
Dim range2 As Range: Set range2 = Range("F2:H11")
Dim y As Range
Dim x As Range
Dim Data As Variant: ReDim Data(1 To range1.Cells.CountLarge, 1 To 2)
Dim i As Long
For Each y In range1.Cells
i = i + 1
Data(i, 1) = y.Value
Data(i, 2) = Application.CountIf(range2, Data(i, 1))
Next y
' Write to the Immediate window.
For i = 1 To UBound(Data, 1)
Debug.Print Data(i, 1), Data(i, 2)
Next i
' Write to a two-column range.
With Range("A2").Resize(, 2)
.Resize(Rows.Count - .Row + 1).ClearContents
.Resize(UBound(Data, 1)).Value = Data
End With
End Sub
Sub testUniqueArrayLoop()
Dim range1 As Range: Set range1 = Range("D2:D11")
Dim range2 As Range: Set range2 = Range("F2:H11")
Dim y As Range
Dim x As Range
Dim Data As Variant: ReDim Data(1 To range1.Cells.CountLarge, 1 To 2)
Dim i As Long
For Each y In range1.Cells
If IsError(Application.Match(y.Value, Data, 0)) Then
i = i + 1
Data(i, 1) = y.Value
Data(i, 2) = 0
For Each x In range2.Cells
If StrComp(x.Value, y.Value, vbTextCompare) = 0 Then
Data(i, 2) = Data(i, 2) + 1
End If
Next x
End If
Next y
Dim k As Long: k = i
' Write to the Immediate window.
For i = 1 To k
Debug.Print Data(i, 1), Data(i, 2)
Next i
' Write to a two-column range.
With Range("A2").Resize(, 2)
.Resize(Rows.Count - .Row + 1).ClearContents
.Resize(k).Value = Data
End With
End Sub
Sub testUniqueArrayCountIf()
Dim range1 As Range: Set range1 = Range("D2:D11")
Dim range2 As Range: Set range2 = Range("F2:H11")
Dim y As Range
Dim x As Range
Dim Data As Variant: ReDim Data(1 To range1.Cells.CountLarge, 1 To 2)
Dim i As Long
For Each y In range1.Cells
If IsError(Application.Match(y.Value, Data, 0)) Then
i = i + 1
Data(i, 1) = y.Value
Data(i, 2) = Application.CountIf(range2, Data(i, 1))
End If
Next y
Dim k As Long: k = i
' Write to the Immediate window.
For i = 1 To k
Debug.Print Data(i, 1), Data(i, 2)
Next i
' Write to a two-column range.
With Range("A2").Resize(, 2)
.Resize(Rows.Count - .Row + 1).ClearContents
.Resize(k).Value = Data
End With
End Sub
I made a collection object that will add a new counter for every y. In the second loop it increments the last element of the collection by one. At the end if you look at each element in the collection it should contain the number of times x=y per y element.
Dim pos As Range
Dim range1 As Range
Dim range2 As Range
Dim x As Range
Dim y As Range
Dim countXinY As New Collection
Set pos = Sheets("Sheet1").Cells(5, 6)
For Each y In range1
countXinY.Add 0
Set pos = pos.Offset(3, 0) 'Currently setting 3 spaces between each change of Y
For Each x In range2
If y = x Then
countXinY(countXinY.Count) = countXinY(countXinY.Count) + 1
x.Cells(, 5).Copy pos
Set pos = pos.Offset(1, 0)
End If
Next x
Next y

Resources