I have three macros that compare two columns
The one I am using is vary slow on a large file but works
Sub MatchPermissionGiverAndTarget()
Dim LastRow As Long
Dim ws As Excel.Worksheet
GoFast False
Set ws = ActiveWorkbook.Sheets("Helper")
LastRow = ws.Range("A" & ws.Rows.count).End(xlUp).Row
Range("E1").EntireColumn.Insert
Range("E1").FormulaR1C1 = "name"
With ws.Range("E2:E" & LastRow)
.Formula = "=INDEX(B:B,MATCH($D2,$B:$B,0))"
.Value = .Value
End With
Columns("D:D").EntireColumn.Delete
GoFast True
End Sub
And this one I found by #mehow Here: Fast compare method of 2 columns
But I can not figure out how to apply it so it dose what the first one dose
Any help on this is appreciated
Sub Main()
Application.ScreenUpdating = False
Dim stNow As Date
stNow = Now
Dim arr As Variant
arr = Range("B2:A" & Range("B" & Rows.Count).End(xlUp).Row).Value
Range("E1").EntireColumn.Insert
Range("E1").FormulaR1C1 = "name"
Dim varr As Variant
varr = Range("D2:D" & Range("D" & Rows.Count).End(xlUp).Row).Value
Dim x, y, match As Boolean
For Each x In arr
match = False
For Each y In varr
If x = y Then match = True
Next y
If Not match Then
Range("D" & Range("D" & Rows.Count).End(xlUp).Row + 1) = x
End If
Next
Columns("D:D").EntireColumn.Delete
Debug.Print DateDiff("s", stNow, Now)
Application.ScreenUpdating = True
End Sub
Or This one from same thread by #Reafidy
Sub HTH()
Application.ScreenUpdating = False
With Range("E2", Cells(Rows.Count, "E").End(xlUp)).Offset(, 1)
.Formula = "=VLOOKUP(B2,D:D,1,FALSE)"
.Value = .Value
.SpecialCells(xlCellTypeConstants, 16).Offset(, -1).Copy Range("D" & Rows.Count).End(xlUp).Offset(1)
.ClearContents
End With
Application.ScreenUpdating = True
End Sub
try this one:
Sub Main()
Dim ws As Worksheet
Dim stNow As Date
Dim lastrow As Long, lastrowB As Long
Dim match As Boolean
Dim k As Long
Dim arr, varr, v, a, res
Application.ScreenUpdating = False
stNow = Now
Set ws = ActiveWorkbook.Sheets("Helper")
With ws
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
lastrowB = .Range("B" & .Rows.Count).End(xlUp).Row
arr = .Range("B2:B" & lastrowB).Value
varr = .Range("D2:D" & lastrow).Value
.Range("E1").EntireColumn.Insert
.Range("E1").FormulaR1C1 = "name"
End With
k = 1
ReDim res(1 To lastrow, 1 To 1)
For Each v In varr
match = False
'if value from column D (v) contains in column B
For Each a In arr
If a = v Then
match = True
Exit For
End If
Next a
If match Then
res(k, 1) = v
Else
res(k, 1) = CVErr(xlErrNA)
End If
k = k + 1
Next v
With ws
.Range("E2:E" & lastrow).Value = res
.Range("D:D").Delete
End With
Debug.Print DateDiff("s", stNow, Now)
Application.ScreenUpdating = True
End Sub
Related
This sub clears duplicate rows between two columns.
If it finds a new pair in columns F & G, it will clear that pair throughout F & G.
I'm trying to clear values that are directly below the original values.
I'm trying to reset after a duplicate been cleared, so that it doesn't clear values that aren't directly below the original values.
Sub clearDups1()
Dim lngMyRow As Long
Dim lngMyCol As Long
Dim lngLastRow As Long
Dim objMyUniqueData As Object
Application.ScreenUpdating = False
lngLastRow = Range("F:G").Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).row
Set objMyUniqueData = CreateObject("Scripting.Dictionary")
For lngMyRow = 1 To lngLastRow 'Assumes the data starts at row 1. Change to suit if necessary.
If objMyUniqueData.Exists(CStr(Cells(lngMyRow, 6) & Cells(lngMyRow, 7))) = False Then
objMyUniqueData.Add CStr(Cells(lngMyRow, 6) & Cells(lngMyRow, 7)), Cells(lngMyRow, 6) & Cells(lngMyRow, 7)
Else
Range(Cells(lngMyRow, 6), Cells(lngMyRow, 7)).ClearContents
End If
Next lngMyRow
Set objMyUniqueData = Nothing
Application.ScreenUpdating = True
End Sub
Any input appreciated.
You don't need a dictionary for this:
Sub clearDups1()
Dim lngMyRow As Long, lngLastRow As Long, ws As Worksheet
Dim k As String, kPrev As String
Set ws = ActiveSheet
lngLastRow = ws.Range("F:G").Find("*", SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).row
Application.ScreenUpdating = False
kPrev = Chr(0) 'won't occur in your data
For lngMyRow = 1 To lngLastRow 'Assumes the data starts at row 1. Change to suit if necessary.
k = CStr(ws.Cells(lngMyRow, 6).Value) & "<>" & CStr(ws.Cells(lngMyRow, 7).Value)
If kCurr = k Then 'same as previous row?
ws.Cells(lngMyRow, 6).Resize(1, 2).ClearContents
End If
kPrev = k 'set as key for previous row
Next lngMyRow
Application.ScreenUpdating = True
End Sub
You can also try this code. It does what you have asked.
Leave the first occurring of the same dups
Start from the bottom to delete them and leave the final which in our case will be original
Using the above ways you can achieve what you have asked for.
Sub clearDups()
Dim lR As Long, r As Long
Dim x As 99999
Dim f(x), g(x) As String
Dim lRow As Long, lCol As Long, i As Long
lRow = Range("F" & Rows.Count).End(xlUp).Row
For lR = 2 To lRow
f(lR - 1) = Cells(lR, "F").Value
g(lR - 1) = Cells(lR, "G").Value
Next
For Each s In f
i = i + 1
If Application.CountIf(Range("F1:G" & lRow), s) = 2 Then
Cells(i, "F").Value = ""
Cells(i, "G").Value = ""
End If
Next
End Sub
I would appreciate if I can get help in creating this macro. I have two workbooks, and want to compare the specific column from 1st workbook, Ex: Column H with next work book, Ex: column A. After comparison highlight the matching cells in 1st workbook. I have tried below script for comparison, it is executing successfully, but not seeing any result.
Sub test()
Dim ws1 As Worksheet, ws2 As Worksheet, w(), i As Long
Dim r As Range, myCol As String
Set ws1 = ThisWorkbook.Sheets(1)
Set ws2 = Workbooks("workbook.xlsx").Sheets(1)
With CreateObject("VBScript.RegExp")
.Pattern = "^([a-z]|[a-h][a-z]|[a-i][a-v])$"
.IgnoreCase = True
Do
myCol = InputBox("Enter Column")
Loop While Not .test(myCol)
End With
With CreateObject("Scripting.Dictionary")
.comparemode = vbTextCompare
For Each r In ws1.Range(myCol & "1", ws1.Range(myCol & Rows.Count).End(xlUp))
If Not IsEmpty(r) And Not .exists(r.Value) Then
ReDim w(0): w(0) = r.Row
.Add r.Value, w
Else
w = .Item(r.Value)
ReDim Preserve w(UBound(w) + 1)
w(UBound(w)) = r.Row
.Item(r.Value) = w
End If
Next
For Each r In ws2.Range("a1", ws2.Range("a" & Rows.Count).End(xlUp))
If .exists(r.Value) Then
For i = 0 To UBound(.Item(r.Value))
ws1.Range(myCol & .Item(r.Value)(i)).Offset(, 1).Resize(, 23).Value = _
r.Offset(, 1).Resize(, 23).Value
Next
End If
Next
End With
Set ws1 = Nothing: Set ws2 = Nothing
End Sub
Try
Sub test()
Dim ws1 As Worksheet, ws2 As Worksheet, w(), i As Long, n As Integer
Dim r As Range, myCol As String, wbname As String, msg As String
Set ws1 = ThisWorkbook.Sheets(1)
Dim myworkbooks As Variant, mycolors As Variant
' workbooks to compare
myworkbooks = Array("Workbook1.xlsx", "Workbook2.xlsx", "Workbook3.xlsx")
mycolors = Array(vbYellow, vbGreen, vbBlue)
' select column
With CreateObject("VBScript.RegExp")
.Pattern = "^([a-z]|[a-h][a-z]|[a-i][a-v])$"
.IgnoreCase = True
Do
myCol = InputBox("Enter Column")
Loop While Not .test(myCol)
End With
' build dictionary
With CreateObject("Scripting.Dictionary")
.comparemode = vbTextCompare
For Each r In ws1.Range(myCol & "1", ws1.Range(myCol & Rows.Count).End(xlUp))
If IsEmpty(r) Then
' skip empty cells
Else
If Not .exists(r.Value) Then
ReDim w(0): w(0) = r.Row
.Add r.Value, w
Else
w = .Item(r.Value)
ReDim Preserve w(UBound(w) + 1)
w(UBound(w)) = r.Row
.Item(r.Value) = w
End If
End If
Next
' compare and highlight match
For n = 0 To UBound(myworkbooks)
Debug.Print "Opening " & myworkbooks(n)
msg = msg & vbCrLf & myworkbooks(n)
Set ws2 = Workbooks(myworkbooks(n)).Sheets(1)
For Each r In ws2.Range("a1", ws2.Range("a" & Rows.Count).End(xlUp))
If .exists(r.Value) Then
For i = 0 To UBound(.Item(r.Value))
ws1.Range(myCol & .Item(r.Value)(i)).Interior.color = mycolors(n)
Next
End If
Next r
Next n
End With
Set ws1 = Nothing: Set ws2 = Nothing
MsgBox "Completed scanning" & msg, vbInformation
End Sub
I have values in column B (green, blue, white....) and I want to count them and the result must appear in column A in the following format (green01, green02, green03...., blue01, blue02, blue03, blue04...., white01, white 02...).
The result must look like in this photo
I have searched the net for a macro, but I didn't find one to fit my needs.
THX
No VBA needed, in A1:
=B1&TEXT(COUNTIF(B$1:B1,B1),"00")
Try the next code, please:
Sub testCountSortColors()
Dim sh As Worksheet, lastRow As Long, i As Long, c As Long
Set sh = ActiveSheet
lastRow = sh.Range("B" & Rows.count).End(xlUp).Row
sh.Range("B1:B" & lastRow).Sort key1:=sh.Range("B1"), order1:=xlAscending, Header:=xlYes
For i = 2 To lastRow
If sh.Range("B" & i).value <> sh.Range("B" & i - 1).value Then
c = 1
Else
c = c + 1
End If
sh.Range("A" & i).value = sh.Range("B" & i).value & Format(c, "00")
sh.Range("A" & i).Font.Color = sh.Range("B" & i).Font.Color
Next
End Sub
I thought you maybe have column headers...
A Unique Count
Adjust the values in the constants section.
Option Explicit
Sub countUnique()
Const SourceColumn As Variant = 2 ' e.g. 2 or "B"
Const TargetColumn As Variant = 1 ' e.g. 1 or "A"
Const FirstRow As Long = 1
Dim rng As Range
Dim dict As Object
Dim Key As Variant
Dim Source As Variant, Target As Variant
Dim i As Long, UB As Long
Dim CurrString As String
Set rng = Columns(SourceColumn).Find(What:="*", _
LookIn:=xlFormulas, SearchDirection:=xlPrevious)
If rng Is Nothing Then GoTo exitProcedure
If rng.Row < FirstRow Then GoTo exitProcedure
Source = Range(Cells(FirstRow, SourceColumn), rng)
Set rng = Nothing
UB = UBound(Source)
Set dict = CreateObject("Scripting.Dictionary")
For i = 1 To UB
If Source(i, 1) <> "" Then
dict(Source(i, 1)) = dict(Source(i, 1)) + 1
End If
Next i
ReDim Target(1 To UB, 1 To 1)
For i = UB To 1 Step -1
CurrString = Source(i, 1)
If CurrString <> "" Then
Target(i, 1) = CurrString & Format(dict(CurrString), "00")
dict(CurrString) = dict(CurrString) - 1
End If
Next i
With Cells(FirstRow, TargetColumn)
.Resize(Rows.Count - FirstRow + 1).ClearContents
.Resize(UB) = Target
End With
MsgBox "Operation finished successfully."
exitProcedure:
End Sub
I try to compare two columns and get the non-matching results listed somewhere else.
So far I've come up with the following:
Sub match_columns()
Dim i, Lastrow1, Lastrow3 As Integer
Dim found As Range
With Worksheets("sht1")
Lastrow1 = .Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To Lastrow1
answer1 = .Range("A" & i).Value
Set found = Sheets("sht2").Columns("A:A").Find(what:=answer1)
If found Is Nothing Then
Set rngNM = .Range("A" & i.Row)
Else
Set rngNM = Union(rngNM, .Range("A" & i.Row))
End If
Next i
End With
If Not rngNM Is Nothing Then rngNM.Copy Worksheets("sht3").[A2]
Worksheets("sht3").[A1] = "title"
Lastrow3 = Sheets("sht3").Range("A" & Rows.Count).End(xlUp).Row
Sheets("sht3").Range("A2:A" & Lastrow3).Copy
End Sub
I currently get an "Runtime error 424; Object required" for the following:
Set rngNM = .Range("A" & i.Row)
Where is my code wrong?
Try this code
Sub Compare_Two_Columns()
Dim ws As Worksheet, sh As Worksheet, out As Worksheet, c As Range, i As Long, m As Long, k As Long
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Worksheets("Sheet1")
Set sh = ThisWorkbook.Worksheets("Sheet2")
Set out = ThisWorkbook.Worksheets("Sheet3")
m = ws.Range("A" & Rows.Count).End(xlUp).Row
ReDim a(1 To m)
For i = 1 To m
Set c = sh.Range("A:A").Find(What:=ws.Cells(i, 1).Value, LookAt:=xlWhole)
If c Is Nothing Then k = k + 1: a(k) = ws.Cells(i, 1).Value
Next I
If k > 0 Then
With out
.Range("A1").Value = "Title"
.Range("A2").Resize(k).Value = Application.Transpose(a)
End With
End If
Application.ScreenUpdating = True
MsgBox "Done...", 64
End Sub
I am new to this and don't know why my sheet is not copying over the the new worksheet? I can't find the error in my VBA.
Private Sub Adminminreport_Click()
Application.ScreenUpdating = False
Dim i&, LR&, count&
LR = Worksheets("Parts").Range("J" & Rows.count).End(xlUp).Row
Set newWS = Worksheets.Add
Worksheets("Parts").Range(Worksheets("Parts").Cells(1, 1), Worksheets("Parts").Cells(1, 13)).Copy newWS.Range("A1")
count = 2
For i = 2 To LR
If Range("J" & i).Value < Range("L" & i).Value Then
Worksheets("Parts").Range(Worksheets("Parts").Cells(i, 1), Worksheets("Parts").Cells(i, 13)).Copy newWS.Range("A" & count)
count = count + 1
End If
Next i
Application.ScreenUpdating = True
Unload Me
newWS.Activate
End Sub
It's good practice to always qualify a Range object with its parent worksheet. Otherwise you're relying on a certain sheet being active when your code runs...
Private Sub Adminminreport_Click()
Dim i As Long, LR As Long, count As Long
Dim newWS As Worksheet, partsWS As Worksheet
Set newWS = Worksheets.Add()
Set partsWS = Worksheets("Parts")
Application.ScreenUpdating = False
LR = partsWS.Range("J" & Rows.count).End(xlUp).Row
Range(partsWS.Cells(1, 1), partsWS.Cells(1, 13)).Copy _
newWS.Range("A1")
count = 2
For i = 2 To LR
If partsWS.Range("J" & i).Value < partsWS.Range("L" & i).Value Then
Range(partsWS.Cells(i, 1), partsWS.Cells(i, 13)).Copy _
newWS.Range("A" & count)
count = count + 1
End If
Next i
Application.ScreenUpdating = True
newWS.Activate
Unload Me
End Sub