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
Related
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'm new to macros and VBA in Excel. Is there a way to check if the Testvalue is between Value 1 and Value 2, and move to the corresponding sheet? And if it's not, move to the next row and repeat.
E.g.
With the testvalue 3742 sheet A21 should be selected.
Simply iterate over each row until required condition is met:
Dim testVal As Long, r As Integer
Dim yourSheet As Worksheet
Set yourSheet = Sheet1
With yourSheet
testVal = .Range("E2").Value
r = 2
Do Until (.Range("A" & r).Value <= testVal) And _
(.Range("B" & r).Value >= testVal)
ThisWorkbook.Worksheets(.Range("C" & r).Value).Activate
r = r + 1
Loop
End With
In my opinion, instead of looping each row is faster if you use Find method.
Sub test()
Dim rngSearchA As Range, rngSearchB As Range, rngFoundA As Range, rngFoundB As Range
Dim strValue As String, strSheetName As String
Dim LastRowA As Long, LastRowB As Long
With ThisWorkbook.Worksheets("Sheet1")
strValue = .Range("E2").Value
strSheetName = ""
LastRowA = .Cells(.Rows.Count, "A").End(xlUp).Row
LastRowB = .Cells(.Rows.Count, "B").End(xlUp).Row
Set rngSearchA = .Range("A2:A" & LastRowA)
Set rngSearchB = .Range("B2:B" & LastRowB)
Set rngFoundA = rngSearchA.Find(strValue, LookIn:=xlValues, Lookat:=xlWhole)
Set rngFoundB = rngSearchB.Find(strValue, LookIn:=xlValues, Lookat:=xlWhole)
If Not rngFoundA Is Nothing And Not rngFoundB Is Nothing Then
If .Range("C" & rngFoundA.Row).Value <> .Range("C" & rngFoundB.Row).Value Then
MsgBox "Searching value appears in both columns with different Sheet name."
Else
strSheetName = .Range("C" & rngFoundA.Row).Value
End If
ElseIf Not rngFoundA Is Nothing Or Not rngFoundB Is Nothing Then
If Not rngFoundA Is Nothing Then
strSheetName = .Range("C" & rngFoundA.Row).Value
Else
strSheetName = .Range("C" & rngFoundB.Row).Value
End If
Else
MsgBox "Value not found!"
End If
If strSheetName <> "" Then
ThisWorkbook.Worksheets(strSheetName).Activate
End If
End With
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 adapted code I found online.
It finds the string "car" in column A and returns the rows as an array
It assigns a variable to the length of the array (how many matches it found)
It assigns a variable to generate a random number between 0 and the length of the array
It then prints a random matching row's value into K3
Dim myArray() As Variant
Dim x As Long, y As Long
Dim msg As String
With ActiveSheet.Range("A1:A" & ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row)
Set c = .find("Car", LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Address
Do
ReDim Preserve myArray(y)
myArray(y) = c.Row
y = y + 1
Set c = .findNext(c)
If c Is Nothing Then
GoTo DoneFinding
End If
Loop While c.Address <> firstAddress
End If
DoneFinding:
End With
For x = LBound(myArray) To UBound(myArray)
msg = msg & myArray(x) & " "
Next x
ArrayLen = UBound(myArray) - LBound(myArray)
random_index = WorksheetFunction.RandBetween(0, ArrayLen)
MsgBox myArray(random_index)
Dim test As String
test = "B" & myArray(random_index)
Range("K3").Value = Range(test)
Example
I'm struggling with adapting the find code to allow for multiple criteria. So in my example, it finds "Car". What if I want to find matches that had "Car" in column A and "Red" in column D?
I tried
With ActiveSheet.Range("A1:A" & "D1:D" & ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row & ActiveSheet.Range("D" & Rows.Count).End(xlUp).Row)
Set c = .find("Car", "Red", LookIn:=xlValues)
I get type mismatch on the Set line.
In case it is confusing, it currently looks for a string e.g. "Car" but I will eventually link this to the variable which will be assigned to a data validation list. So if the user chooses "car" from a drop down list, this is what it will search for.
Maybe Advancde Filter is something that fit your needs:
Example Code
Option Explicit
Public Sub FilterData()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("YourSheetName")
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim CriteriaRange As Range
Set CriteriaRange = ws.Range("A1", "E2")
Dim DataRange As Range
Set DataRange = ws.Range("A4", "E" & LastRow)
DataRange.AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:=CriteriaRange, Unique:=False
End Sub
Public Sub ShowAll()
On Error Resume Next
ActiveSheet.ShowAllData
On Error GoTo 0
End Sub
Edit according comment:
You can use the advanced filter and then loop through the filter results:
Option Explicit
Public CurrentRow As Long
Public Sub FilterData()
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("YourSheetName")
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim CriteriaRange As Range
Set CriteriaRange = ws.Range("A1", "E2")
Dim DataRange As Range
Set DataRange = ws.Range("A4", "E" & LastRow)
DataRange.AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:=CriteriaRange, Unique:=False
End Sub
Public Sub ShowAll()
On Error Resume Next
ActiveSheet.ShowAllData
CurrentRow = 1
On Error GoTo 0
End Sub
Public Sub GetNextResult()
FilterData
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("YourSheetName")
Dim LastRow As Long
LastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim DataRange As Range
Set DataRange = ws.Range("A4", "E" & LastRow)
Dim FilteredData As Range
Set FilteredData = DataRange.Resize(ColumnSize:=1).SpecialCells(xlCellTypeVisible)
If CurrentRow + 1 > FilteredData.Cells.Count Then
CurrentRow = 1
End If
CurrentRow = CurrentRow + 1
Dim i As Long
Dim Cell As Variant
For Each Cell In FilteredData
i = i + 1
If i = CurrentRow Then
Cell.EntireRow.Select
'or
'MsgBox Cell.Value & vbCrLf & Cell.Offset(0, 1) & vbCrLf & Cell.Offset(0, 2) & vbCrLf & Cell.Offset(0, 3) & vbCrLf & Cell.Offset(0, 4)
End If
Next Cell
End Sub
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