I found a macro to count & Highlight Duplicates. My friend & I have tried to get it working, but have not been able to get it working. Column A ( Name), Column L ( Yes - Filter), Column M (Duplicate). In addition to getting the code working, we are trying to get the macro to filter on Yes in column L, and Print Duplicate in Column M. Please advise what is wrong & how to fix the problem. Here is the code:
Option Explicit
Sub Find_Duplicates()
Dim col As Integer
Dim rng As String
col = 3
rng = "A5:A"
HighLightDuplicates rng, col
ShowMaxOnly rng, col
End Sub
Sub HighLightDuplicates(ByVal rng As String, ByVal col As Integer)
Dim i, j As Integer
Dim temp As Variant
Range(rng).Select
Dim Count As Integer
Count = 1
For i = 1 To Selection.Count
temp = Range(Left(rng, 1) & i)
For j = i + 1 To Selection.Count
If temp = Range(Left(rng, 1) & j) And temp <> "" Then
Count = Count + 1 'increase the number of duplicates
'highlight the duplicates
Range(Left(rng, 1) & i).Interior.Color = RGB(0, 100, 255)
Range(Left(rng, 1) & j).Interior.Color = RGB(0, 100, 255)
End If
Next
'show the number of duplicates
If Count > 1 Then
Cells(i, col) = Count & " duplicates"
End If
'reset count
Count = 1
Next
End Sub
'show only the biggest number of duplicates in a group
Sub ShowMaxOnly(ByVal rng As String, ByVal col As Integer)
Dim i, j As Integer
Dim temp As Variant
Range(rng).Select
i = 1
For i = 1 To Selection.Count
temp = Range(Left(rng, 1) & i)
For j = i + 1 To Selection.Count
If temp = Range(Left(rng, 1) & j) And temp <> "" Then
Cells(j, col) = "" 'remove the smaller numbers duplicates
End If
Next
Next
End Sub
Maybe this would work for you.
It adds the formula and then uses conditional formatting to highlight the cells.
Public Sub Find_Duplicates()
Dim wrkSht As Worksheet 'The worksheet that you're lookin for duplicates in.
Dim rng As Range 'The range containing the duplicates.
Dim Col As Long 'The last column containing data +1
Set wrkSht = ThisWorkbook.Worksheets("Sheet1")
With wrkSht
'Reference to whole data range.
Set rng = .Range("A5:L25")
'If the sheet is blank an error will be thrown when trying to find the last column.
'This code looks for the last column - you could just set Col to equal the last column number + 1.
On Error Resume Next
Col = .Cells.Find("*", , , , xlByColumns, xlPrevious).Column
Err.Clear
On Error GoTo 0
If Col = 0 Then Col = 1
'Place a COUNTIF formula in the last column.
rng.Offset(, Col).Columns(1).FormulaR1C1 = "=COUNTIF(" & rng.Columns(1).Address(ReferenceStyle:=xlR1C1) & ",RC" & rng.Column & ") & "" duplicates."""
With rng
'Add conditional formatting to first column in range: If the COUNTIF formula is showing >1 then highlight cell.
With .Columns(1)
'This formula is =VALUE(LEFT($M5,FIND(" ",$M5)-1))>1.
'It returns only the number from the duplicate count and checks it is higher than 1.
.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=VALUE(LEFT(" & rng.Offset(, Col).Cells(1).Address(RowAbsolute:=False) & ",FIND("" ""," & _
rng.Offset(, Col).Cells(1).Address(RowAbsolute:=False) & ")-1))>1"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
.FormatConditions(.FormatConditions.Count).Interior.Color = RGB(0, 100, 255)
End With
'Apply filter to your range.
.AutoFilter
.AutoFilter Field:=12, Criteria1:="Yes"
End With
End With
End Sub
Updated code:
This will always place the last column as 1 to the right of the range set in the variable rng.
Public Sub Find_Duplicates()
Dim wrkSht As Worksheet 'The worksheet that you're lookin for duplicates in.
Dim rng As Range 'The range containing the duplicates.
Dim rLastCol '1 column to right of rng.
Dim Col As Long 'The last column containing data +1
Set wrkSht = ThisWorkbook.Worksheets("Sheet1")
With wrkSht
'Reference to whole data range.
Set rng = .Range("A5:L25")
Set rLastCol = rng.Offset(, 1).Columns(rng.Columns.Count)
'Place a COUNTIF formula in the last column.
rLastCol.FormulaR1C1 = "=COUNTIF(" & rng.Columns(1).Address(ReferenceStyle:=xlR1C1) & ",RC" & rng.Column & ") & "" duplicates."""
With rng
'Add conditional formatting to first column in range: If the COUNTIF formula is showing >1 then highlight cell.
With .Columns(1)
'This formula is =VALUE(LEFT($M5,FIND(" ",$M5)-1))>1.
'It returns only the number from the duplicate count and checks it is higher than 1.
.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=VALUE(LEFT(" & rLastCol.Cells(1).Address(RowAbsolute:=False) & ",FIND("" ""," & _
rLastCol.Cells(1).Address(RowAbsolute:=False) & ")-1))>1"
.FormatConditions(.FormatConditions.Count).SetFirstPriority
.FormatConditions(.FormatConditions.Count).Interior.Color = RGB(0, 100, 255)
End With
End With
End With
End Sub
Related
I am looking for a code, that can find each cell that starts with the number "2347" in column L. I want to get the cell adresses for these cells and display it in a MessageBox for example "Msgbox: Cells L3500:L3722 has a value starts starts with "2347" "
Sub Findrow()
Dim MyVal As Integer
Dim LastRow As Long
MyVal = LEFT(c.Value,4) = "2347" _
LastRow = Cells(Rows.Count, "L").End(xlUp).Row
For Each c In Range("L2:L" & LastRow)
If c.Value = Myval Then
This is my code so far. Hope someone can help me!
Using arrays is quite fast
Option Explicit
Public Sub FindIDInColL()
Const VID = "2347" 'Value to find
Dim ws As Worksheet, arrCol As Variant, found As Variant
Set ws = ActiveSheet 'Or Set ws = ThisWorkbook.Worksheets("Sheet3")
arrCol = ws.Range(ws.Cells(2, "L"), ws.Cells(ws.Rows.Count, "L").End(xlUp))
ReDim found(1 To UBound(arrCol))
Dim r As Long, f As Long, msg As String
f = 1
For r = 1 To UBound(arrCol) 'Iterate vals in col L, excluding header row
If Not IsError(arrCol(r, 1)) Then 'Ignore errors
If Len(arrCol(r, 1)) > 3 Then 'Check only strings longer than 3 letters
If Left$(arrCol(r, 1), 4) = VID Then 'Check first 4 letters
found(f) = r + 1 'Capture rows containing value (header offset)
f = f + 1
End If
End If
End If
Next
If f > 1 Then 'If any cells found
ReDim Preserve found(1 To f - 1) 'Drop unused array items
msg = "Cells in col L starting with """ & VID & """" & vbNewLine & vbNewLine
MsgBox msg & " - L" & Join(found, ", L"), , "Total Found: " & f - 1
Else
MsgBox "No cells starting with """ & VID & """ found in col L", , "No matches"
End If
End Sub
Even faster when using the string versions of these functions
Left$() Mid$() Right$() Chr$() ChrW$() UCase$() LCase$()
LTrim$() RTrim$() Trim$() Space$() String$() Format$()
Hex$() Oct$() Str$() Error$
They are more efficient (if Null is not a concern), as pointed out by QHarr
You may try this:
Option Explicit
Sub Findrow()
Dim MyVal As String ' "2347" is a String
Dim LastRow As Long
Dim c As Range, myCells As Range
MyVal = "2347"
LastRow = cells(Rows.Count, "L").End(xlUp).row
Set myCells = Range("M2") 'initialize cells with a dummy cell certainly out of relevant one
For Each c In Range("L2:L" & LastRow)
If Left(c.Value2, 4) = MyVal Then Set myCells = Union(myCells, c) ' if current cell matches criteria then add it to cells
Next
If myCells.Count > 1 Then MsgBox "Cells " & Intersect(myCells, Range("L:L")).Address(False, False) & " have values starting with ‘2347’" ' if there are other cells than the dummy one then get rid of this latter and show their addresses
End Sub
I want to copy duplicate rows from a sheet to another by analyzing multiple columns in excel, I can do it by applying Nested For loops to compare multiple columns but number of rows in my sheet is around 6000. So if I apply nested For loop to compare rows by analyzing 2 columns it requires around 17991001 iterations, which slows down my System. Is there any fast way to do that???
my Function is
Sub findDuplicates(ByVal sheet As Worksheet, name As String, ByRef row As Integer, ByVal Sheet2 As Worksheet)
Dim i As Integer
Dim numRow As Integer
'Dim matchFound As Long
'Dim myRange1 As Range
'Dim myRange2 As Range
numRow = sheet.Range("J2", sheet.Range("J2").End(xlDown)).Rows.Count
With Sheet2
Range(Cells(row, "A"), Cells(row, "N")).MergeCells = True
With Cells(row, "A")
.Font.name = "Bell MT"
.Font.FontStyle = "Bold Italic"
.Font.Size = 20
.Font.Color = RGB(255, 99, 71)
.Value = "Multiple Forms Found in " & name & " for single household"
End With
row = row + 1
End With
For i = 1 To numRow + 1
'matchFound
'If i <> matchFound Then
sheet.Rows(i).Copy Sheet2.Rows(row)
row = row + 1
'sheet.Rows(matchFound).Copy Sheet2.Rows(row)
'row = row + 1
'End If
Next i
End Sub
Note - I added some comments to make you understand what I want to do.
The Summery of my function is to take two sheets and check the J and K columns of sheet 1, If two rows found same J and K column's value then both rows are copied to sheet2 (next to each other)
Try this. Modified from Siddharth Rout's answer here.
Private Sub CommandButton2_Click()
Dim col As New Collection
Dim SourceSheet As Worksheet
Dim DestSheet As Worksheet
Dim i As Long
Dim lLastRow As Long
Application.ScreenUpdating = False
Set SourceSheet = ThisWorkbook.Sheets("Sheet1")
Set DestSheet = Worksheets("Sheet2")
lLastRow = SourceSheet.Cells(Rows.Count, 10).End(xlUp).row
DestSheetLastRow = 1
With SourceSheet
For i = 1 To lLastRow
On Error Resume Next
col.Add i, CStr(.Range("J" & i).Value) 'Add elements to collection
If Err.Number <> 0 Then 'If element already present
TheVal = CStr(SourceSheet.Range("J" & i).Value) 'Get the duplicate value
TheIndex = col(TheVal) 'Get the original position of duplicate value in the collection (i.e., the row)
If (.Cells(i, 11).Value = .Cells(TheIndex, 11).Value) Then 'Check the other column (K). If same value...
SourceSheet.Range(Cells(TheIndex, 1), Cells(TheIndex, 20)).Copy DestSheet.Cells(DestSheetLastRow, 1) 'Set your range according to your needs. 20 columns in this example
SourceSheet.Range(Cells(i, 1), Cells(i, 20)).Copy DestSheet.Cells(DestSheetLastRow, 21)
DestSheetLastRow = DestSheetLastRow + 1
Err.Clear
End If
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
Finally, This Works for me
Sub findDuplicates(ByVal sheet As Worksheet, name As String, ByRef row As Integer, ByVal Sheet2 As Worksheet)
Dim i As Integer
Dim j As Integer
Dim numRow As Integer
Dim count As Integer
Dim myRange1 As Range
Dim myRange2 As Range
Dim myRange3 As Range
Set myRange1 = sheet.Range("J2", sheet.Range("J2").End(xlDown)).Rows
Set myRange2 = sheet.Range("K2", sheet.Range("K2").End(xlDown)).Rows
numRow = sheet.Range("J2", sheet.Range("J2").End(xlDown)).Rows.count
With Sheet2
Range(Cells(row, "A"), Cells(row, "N")).MergeCells = True
With Cells(row, "A")
.Font.name = "Bell MT"
.Font.FontStyle = "Bold Italic"
.Font.Size = 20
.Font.Color = RGB(255, 99, 71)
.Value = "Multiple Forms Found in " & name & " for single household"
End With
sheet.Rows(1).Copy .Rows(row + 1)
.Rows(row + 1).WrapText = False
row = row + 2
End With
j = row
For i = 1 To numRow + 1
count = WorksheetFunction.CountIfs(myRange1, sheet.Cells(i, "J"), myRange2, sheet.Cells(i, "K"))
If count > 1 Then
sheet.Rows(i).Copy Sheet2.Rows(row)
row = row + 1
End If
Next i
Set myRange3 = Sheet2.Range(Cells(j, 1), Cells(row - 1, 192))
With Sheet2.Sort
.SortFields.Add Key:=Range("J1"), Order:=xlAscending
.SortFields.Add Key:=Range("K1"), Order:=xlAscending
.SetRange myRange3
.Header = xlNo
.Orientation = xlTopToBottom
.Apply
End With
End Sub
I've got this spreadsheet in which I need to Sum up worked hours.
In Column 'I' I've got all worked hours which I sorted through weeknumbers in row 'E' with the following loop I found somewhere on Google (can't remember who wrote it but it works).
Dim i, itotalrows As Integer
Dim strRange As String
itotalrows = ActiveSheet.Range("E20000").End(xlUp).Offset(1, 0).Row
Do While i <= itotalrows
i = i + 1
strRange = "E" & i
strRange2 = "E" & i + 1
If Range(strRange).Text <> Range(strRange2).Text Then
Rows(i + 1).Insert
itotalrows = ActiveSheet.Range("E20000").End(xlUp).Offset(1, 0).Row
i = i + 1
End If
Loop
In the picture you can see one of the cells marked with "Total value of cells up
"
there's a blank every few rows with a cell on 'I' where the total value should go.
Sheet Picture:
Perhaps to sum the groups in column I, based on where the blanks are in column G
Sub x()
Dim r As Range
For Each r In Range("G:G").SpecialCells(xlCellTypeConstants).Areas
r.Cells(r.Count + 1).Offset(, 2).Value = WorksheetFunction.Sum(r.Offset(, 2))
Next r
End Sub
If you were to replace your code with the following, I believe it should do what you expect:
Sub foo()
Dim i, itotalrows As Integer
Dim strRange As String
itotalrows = ActiveSheet.Range("E20000").End(xlUp).Offset(1, 0).Row
Do While i <= itotalrows
i = i + 1
strRange = "E" & i
strRange2 = "E" & i + 1
If Range(strRange).Text <> Range(strRange2).Text Then
Rows(i + 1).Insert
Cells(i + 1, "I").FormulaR1C1 = "=SUMIF(C[-4],R[-1]C[-4],C)"
'when inserting a new row, simply add this formula to add up the values on column I
itotalrows = ActiveSheet.Range("E20000").End(xlUp).Offset(1, 0).Row
i = i + 1
End If
Loop
End Sub
Seeing as your code already does what you wanted (ie. add a new row when values on Column E differ) then adding the formula into that row will add up anything on Column I where the value of Column E is the same.
This is a general approach how to sum the cells in the blank cell.
If this is the input then the right ppicture should be the output:
.
Using this code:
Sub TestMe()
Dim myCell As Range
Dim currentSum As Double
For Each myCell In Worksheets(1).Range("A1:A14")
If myCell = vbNullString Then
myCell = currentSum
myCell.Interior.Color = vbRed
currentSum = 0
Else
currentSum = currentSum + myCell
End If
Next myCell
End Sub
The idea is simply to use a variable for the currentSum and to write it every time when the cell is empty. If it is not empty, increment it with the cell value
I have a problem with a specific excel task. Although I searched the web thoroughly for tips and parts of code I could use, I was not able to get near a functioning solution.
This is my problem:
I have around 30 Worksheets with two columns each.
The number of Rows varies from WS to WS but the two columns on each sheet are equally long.
The first column of each Sheet contains minimum values and the second column holds the respective maximum values.
E.g.
| A | B
1 | 1000 | 1010
2 | 2020 | 2025
Now I need one single column with all values from these intervals including the Max and Min values.
Preferred solution in Column C:
1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 2020, 2021, 2022, 2023, 2024, 2025
I thought of highlighting the two columns and then activating a macro to generate the list. I would then repeat this process for each WS manually. Some sheets have only 4 to 20 rows but some have over 7000 rows.
And if it helps anything: The numbers are postcodes ;-)
I'd be very grateful for any kind of help.
Thanks in advance!
Try this:
Sub Test()
Dim LastRow As Long, ColIndex As Long
Dim i As Long, j As Long
Dim min As Long, max As Long
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
LastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row
ColIndex = 1
For i = 1 To LastRow
min = ws.Cells(i, 1).Value
max = ws.Cells(i, 2).Value
For j = min To max
ws.Cells(ColIndex, 3).Value = j
ColIndex = ColIndex + 1
Next j
Next i
Next ws
End Sub
edited: to have one big string in column "C" (added two lines in each code)
edited 2: added "zip3" solution for having all values listed in "C" column only
you could use either following ways
Option Explicit
Sub zips3()
'list values in column "C" in sequence from all min to max in columns "A" and "B"
Dim sht As Worksheet
Dim cell As Range
For Each sht In ThisWorkbook.Sheets
For Each cell In sht.Range("A1:A" & sht.Cells(sht.Rows.Count, 1).End(xlUp).Row).SpecialCells(xlCellTypeConstants, xlNumbers)
With cell.End(xlToRight).Offset(, 2).Resize(, cell.Offset(, 1).Value - cell.Value + 1)
.FormulaR1C1 = "=RC1+COLUMN()-4"
sht.Range("C" & sht.Cells(sht.Rows.Count, "C").End(xlUp).Row).Offset(1).Resize(.Columns.Count) = Application.Transpose(.Value)
.ClearContents
End With
Next cell
If IsEmpty(sht.Range("C1")) Then sht.Range("C1").Delete (xlShiftUp)
Next sht
End Sub
Sub zips()
'list values in column "C" from corresponding min to max in columns "A" and "B"
Dim sht As Worksheet
Dim cell As Range
Dim j As Long
For Each sht In ThisWorkbook.Sheets
For Each cell In sht.Range("A1:A" & sht.Cells(sht.Rows.Count, 1).End(xlUp).Row).SpecialCells(xlCellTypeConstants, xlNumbers)
For j = cell.Value To cell.Offset(, 1).Value
cell.End(xlToRight).Offset(, 1) = j
Next j
'lines added to have one bg string in column "C"
cell.Offset(, 2).Value2 = "'" & Join(Application.Transpose(Application.Transpose(Range(cell.Offset(, 2), cell.Offset(, 2).End(xlToRight)))), ",")
Range(cell.Offset(, 3), cell.Offset(, 3).End(xlToRight)).ClearContents
Next cell
Next sht
End Sub
Sub zips2()
Dim sht As Worksheet
Dim cell As Range
For Each sht In ThisWorkbook.Sheets
For Each cell In sht.Range("A1:A" & sht.Cells(sht.Rows.Count, 1).End(xlUp).Row).SpecialCells(xlCellTypeConstants, xlNumbers)
cell.End(xlToRight).Offset(, 1).Resize(, cell.Offset(, 1).Value - cell.Value + 1).FormulaR1C1 = "=RC1+COLUMN()-3"
'lines added to have one bg string in column "C"
cell.Offset(, 2).Value2 = "'" & Join(Application.Transpose(Application.Transpose(Range(cell.Offset(, 2), cell.Offset(, 2).End(xlToRight)))), ",")
Range(cell.Offset(, 3), cell.Offset(, 3).End(xlToRight)).ClearContents
Next cell
Next sht
End Sub
A solution you can use as you like would be kinda like this:
Public Function getZIPs(rng As Range) As String
Dim myVal As Variant, str As String, i As Long, j As Long
myVal = Intersect(rng, rng.Parent.UsedRange).Value
For i = 1 To UBound(myVal)
If IsNumeric(myVal(i, 1)) And IsNumeric(myVal(i, 2)) And Len(myVal(i, 1)) > 0 And Len(myVal(i, 2)) > 0 Then
If myVal(i, 1) <= myVal(i, 2) Then
For j = myVal(i, 1) To myVal(i, 2)
str = str & ", " & j
Next
End If
End If
Next
getZIPs = Mid(str, 3)
End Function
Put this into a module and then either go for C1: =getZIPs(A1:B1) and auto fill down or directly =getZIPs(A:B) to get all numbers in one cell or use it in a sub to do it automatically.
If you have any questions, just ask :)
EDIT:
If you want it all exactly in the one-column-way, you can use this (should be fast):
Sub getMyList()
Dim sCell As Range, gCell As Range
Set gCell = ActiveSheet.[A1:B1]
Set sCell = ActiveSheet.[C1]
Dim sList As Variant
While IsNumeric(gCell(1)) And IsNumeric(gCell(2)) And Len(gCell(1)) > 0 And Len(gCell(2)) > 0
If gCell(1) = gCell(2) Then
sCell.Value = gCell(1)
Set sCell = sCell.Offset(1)
Else
sList = Evaluate("ROW(" & gCell(1) & ":" & gCell(2) & ")")
sCell.Resize(UBound(sList)).Value = sList
Set sCell = sCell.Offset(UBound(sList))
End If
Set gCell = gCell.Offset(1)
Wend
End Sub
If you have any questions, just ask ;)
I have two columns of numbers, together they will be unique (composite key). I would like to create an unique ID number (third column) similar to how MS Access would use a primary key. I would like to do this in VBA but I am stuck on how to do it.
My VBA in excel isn't very good so hopefully you can see what I've started to attempt. it may be completely wrong... I don't know?
I don't know how to make the next concatenation and I am unsure about how to go down to the next row correctly.
Sub test2()
Dim var As Integer
Dim concat As String
concat = Range("E2").Value & Range("F2").Value
var = 1
'make d2 activecell
Range("D2").Select
Do Until concat = ""
'if the concat is the same as the row before we give it the same number
If concat = concat Then
var = var
Else
var = var + 1
End If
ActiveCell.Value = var
ActiveCell.Offset(0, 1).Select
'make the new concatination of the next row?
Loop
End Sub
any help is appreciated, thanks.
Give the code below a try, I've added a loop which executes for each cell in the E Column. It checks if the concat value is the same as the concat value in the row above and then writes the id to the D cell.
Sub Test2()
Dim Part1 As Range
Dim strConcat As String
Dim i As Long
i = 1
With ThisWorkbook.Worksheets("NAME OF YOUR SHEET")
For Each Part1 In .Range(.Cells(2, 5), .Cells(2, 5).End(xlDown))
strConcat = Part1 & Part1.Offset(0, 1)
If strConcat = Part1.Offset(-1, 0) & Part1.Offset(-1, 1) Then
Part1.Offset(0, -1).Value = i
Else
i = i + 1
Part1.Offset(0, -1).Value = i
End If
Next Part1
End With
End Sub
Something like this should work, this will return a Unique GUID (Globally Unique Identifier):
Option Explicit
Sub Test()
Range("F2").Select
Do Until IsEmpty(ActiveCell)
If (ActiveCell.Value <> "") Then
ActiveCell.Offset(0, 1).Value = CreateGUID
End If
ActiveCell.Offset(1, 0).Select
Loop
End Sub
Public Function CreateGUID() As String
CreateGUID = Mid$(CreateObject("Scriptlet.TypeLib").GUID, 2, 36)
End Function
If you walk down column D and examine the concatenated values from column E and F with the previous row, you should be able to accomplish your 'primary key'.
Sub priKey()
Dim dcell As Range
With Worksheets("Sheet12")
For Each dcell In .Range(.Cells(2, 4), .Cells(Rows.Count, 5).End(xlUp).Offset(0, -1))
If LCase(Join(Array(dcell.Offset(0, 1).Value2, dcell.Offset(0, 2).Value2), ChrW(8203))) = _
LCase(Join(Array(dcell.Offset(-1, 1).Value2, dcell.Offset(-1, 2).Value2), ChrW(8203))) Then
dcell = dcell.Offset(-1, 0)
Else
dcell = Application.Max(.Range(.Cells(1, 4), dcell.Offset(-1, 0))) + 1
End If
Next dcell
End With
End Sub
You could use collections as well.
Sub UsingCollection()
Dim cUnique As Collection
Dim Rng As Range, LstRw As Long
Dim Cell As Range
Dim vNum As Variant, c As Range, y
LstRw = Cells(Rows.Count, "E").End(xlUp).Row
Set Rng = Range("E2:E" & LstRw)
Set cUnique = New Collection
On Error Resume Next
For Each Cell In Rng.Cells
cUnique.Add Cell.Value & Cell.Offset(, 1), CStr(Cell.Value & Cell.Offset(, 1))
Next Cell
On Error GoTo 0
y = 1
For Each vNum In cUnique
For Each c In Rng.Cells
If c & c.Offset(, 1) = vNum Then
c.Offset(, -1) = y
End If
Next c
y = y + 1
Next vNum
End Sub