Find matched composite data and replace using macro - excel

I have a scenario where I have to look up two columns in worksheet1 and search for match in worksheet2, if any matching column found then replace the value.
Currently I have fixed out to find a match in one column. Here is my code
Sub FindMatch()
Dim x As String
Dim found As Boolean
' Select first line of data.
Range("A2").Select
' Set search variable value.
x = "A"
' Set Boolean variable "found" to false.
found = False
' Set Do loop to stop at empty cell.
Do Until IsEmpty(ActiveCell)
' Check active cell for search value.
If ActiveCell.value = x Then
found = True
Exit Do
End If
' Step down 1 row from present location.
ActiveCell.Offset(1, 0).Select
Loop
' Check for found.
If found = True Then
MsgBox "Value found in cell " & ActiveCell.Address
Else
MsgBox "Value not found"
End If
End Sub
I want to search column "A" and "D" in worksheet 1 against column "A" & "B" in worksheet 2
I searched in SO but didn't see any post similar to my requirement. Can anyone help me out.
Thanks !

This should do it.
Sub FindMatch()
Dim WS_one As Worksheet
Dim WS_two As Worksheet
Set WS_one = Worksheets("Sheet1")
Set WS_two = Worksheets("Sheet2")
' Set worksheets to be used.
Set lastCell = WS_one.Range("A:A").Find _
("*", after:=Cells(1, 1), SearchDirection:=xlPrevious)
'set lastCell as last cell with any value
For x = 1 To lastCell.Row
'Set For loop to run until last cell with value.
With WS_one
'with sheet one only
.Select
Col_ValueA = .Cells(x, 1).Value
Col_ValueD = .Cells(x, 4).Value
'define value to search for
End With
With WS_two
'with sheet two only
.Select
Set findvalue = .Range("A:A").Find _
(Col_ValueA, after:=Cells(1, 1))
'find 1st value equal to column A value
Do
'Do while no match found, and still values to check
If Not findvalue Is Nothing Then
'if value exist then check for match
If .Cells(findvalue.Row, 2).Value = Col_ValueD Then
'check double match
ReplaceValue = .Cells(findvalue.Row, 3).Value
Exit Do
Else
'if second value doesn't match find new Column A value
temp = findvalue.Row
'security check
Set findvalue = .Range("A:A").Find _
(Col_ValueA, after:=Cells(temp, 1))
'find new row
If temp = findvalue.Row Then
'if row doesnt change exit do
Exit Do
End If
End If
Else
'if no column A match found exit do
Exit Do
End If
Loop
End With
If Not ReplaceValue = "" Then
' replacement exists paste in column E and reset replacement value
WS_one.Cells(x, 5).Value = ReplaceValue
ReplaceValue = ""
End If
Next
WS_one.Select
End Sub
Essentially the code matches column A of sheet one with sheet two and if that value matches we check the second value. By the way, you might notice that the code I posted doesn't have select range and Active Cell anymore, try not to use those to often as the are not very secure and tend to make the code slower.

Related

Search for a keyword after some filter and return a value in another column

There is a filter applied to my range of data and i would like to search the keyword "abc" in column "I" after the filtering and return a value "Check" at the very end of my data column "W"
I have not know any example to this function but i do had a code before to search for value and delete the row if the amount is 0.
'Delete rows for zero value
Dim LR As Long, i As Long
With Sheets("tempp")
LR = .Cells.Find(What:="0", SearchDirection:=xlPrevious,
SearchOrder:=xlByRows).Row
For i = LR To 1 Step -1
If .Range("C" & i).Value = 0 Then .Rows(i).Delete
Next i
End With
The below code will search your column I. Please adjust the sheet name to your need. It will return the checked status if "abc" is found. If it is not found you can run your desired check where stipulated.
Sub RangeCheck()
Dim myRange As Range
Dim lRowW as Long
'adjust the sheet name to your sheet name
Set myRange = Sheets("Sheet1").Range("I:I").SpecialCells(xlCellTypeVisible).Find(What:="abc")
If Not myRange Is Nothing Then
'found abc, insert checked - presumably the last row of column W?
lRowW = Sheets("Sheet1").Range("W" & Sheets("Sheet1").Rows.Count).End(xlUp).Row
Sheets("Sheet1").Range("W" & lRowW).Value = "Checked"
'if not last row in column W, then use the below
'Sheets("Sheet1").Range("W1").Value = "Checked"
Else
'if it does not find your string "abc" then insert the check you want to run here
End If
'clear object
Set myRange = Nothing
End Sub
You can use something like this:
Dim c As Range
'Going through each visible cell in *I* column. Change 5000 to the numbers of rows your sheet have
For Each c In Worksheets("tempp").Range("I1:I5000").SpecialCells(xlCellTypeVisible)
'Checking if cell contains abc
If InStr(c.Value, "abc") > 0 Then
Worksheets("tempp").Range("W" & c.Row).Value = "Check"
End If
Next
Let us know if it works!

How to find the differences in column A in 4 different worksheets

I have column K in "filter" sheets that need to be compare with column A in "Active_Buy", "Active_Others" and "Active_Make" sheets accordingly.
First it need to be compare with active_buy sheets. if there is value that in column K (filter sheet) but not in column A (active_Buy sheet), then it need to hold that value and compare it with column A (active_others sheets). If also didnt match, it need to compared with column A (Active_Make sheets).
So, if there is no any match, then the value need to be paste in new sheets name (Unmatched Part No).
I already search everywhere but only can find code that can only compare 2 worksheets only but not more than that.
'Below is the code that i found but only compared two worksheets only
' the concept just same like this but need to hold unmatch value and compare to next worksheet and so on.
Sub compare()
Sheets(3).Activate 'Go to sheet 3
Cells.Clear 'and clear all previous results
Range("a1").Select 'set cursor at the top
Sheets(1).Activate 'go to sheet 1
Range("a1").Select 'begin at the top
Dim search_for As String 'temp variable to hold what we need to look for
Dim cnt As Integer 'optional counter to find out how many rows we found
Do While ActiveCell.Value <> "" 'repeat the follwoing loop until it reaches a blank row
search_for = ActiveCell.Offset(0, 1).Value 'get a hold of the value in column B
Sheets(2).Activate 'go to sheet(2)
On Error Resume Next 'incase what we search for is not found, no errors will stop the macro
Range("b:b").Find(search_for).Select 'find the value in column B of sheet 2
If Err <> 0 Then 'If the value was not found, Err will not be zero
On Error GoTo 0 'clearing the error code
Sheets(1).Activate 'go back to sheet 1
r = ActiveCell.Row 'get a hold of current row index
Range(r & ":" & r).Select 'select the whole row
cnt = cnt + 1 'increment the counter
Selection.Copy 'copy current selection
Sheets(3).Activate 'go to sheet 3
ActiveCell.PasteSpecial xlPasteAll 'Past the entire row to sheet 3
ActiveCell.Offset(1, 0).Select 'go down one row to prepare for next row.
End If
Sheets(1).Activate 'return to sheet 1
ActiveCell.Offset(1, 0).Select 'go to the next row
Loop 'repeat
Sheets(3).Activate 'go to sheet 3 to examine findings
MsgBox "I have found " & cnt & " rows that did not exist in sheet 2"
End Sub
I'd use a For Each loop to run through the values on the 'Filter' sheet, set ranges on each of the other sheets, then check in each of the ranges. I've tested this code and it seems to do the trick. I've commented so you can see what's going on at each line.
(You'll need to adjust the sheet names to match you own, and adjust Application settings to make things run faster if you've got a lot of data.)
Sub compareColumns()
Dim lastRow1, lastRowAB, lastRowAO, lastRowAM, lastRowUMPN As Long
Dim rng1, rngAB, rngAO, rngAM As Range
Dim cell As Range
Dim found As Range
' Define our last rows for each sheet
lastRow1 = ThisWorkbook.Worksheets("FilterSheet").Range("K" & Rows.Count).End(xlUp).Row
lastRowAB = ThisWorkbook.Worksheets("ActiveBuy").Range("A" & Rows.Count).End(xlUp).Row
lastRowAO = ThisWorkbook.Worksheets("ActiveOthers").Range("A" & Rows.Count).End(xlUp).Row
lastRowAM = ThisWorkbook.Worksheets("ActiveMake").Range("A" & Rows.Count).End(xlUp).Row
lastRowUMPN = ThisWorkbook.Worksheets("UnmatchedPartNo").Range("A" & Rows.Count).End(xlUp).Row
' Set the ranges that we'll loop through
Set rng1 = ThisWorkbook.Worksheets("FilterSheet").Range("K1:K" & lastRow1)
Set rngAB = ThisWorkbook.Worksheets("ActiveBuy").Range("A1:A" & lastRowAB)
Set rngAO = ThisWorkbook.Worksheets("ActiveOthers").Range("A1:A" & lastRowAO)
Set rngAM = ThisWorkbook.Worksheets("ActiveMake").Range("A1:A" & lastRowAM)
' Loop through each cell in the filtered sheet
For Each cell In rng1
' Try to find the value in ActiveBuy sheet
Set found = rngAB.Find(cell.Value)
' If not found, try the next sheet
If found Is Nothing Then
Set found = rngAO.Find(cell.Value)
' If not found, try the next sheet
If found Is Nothing Then
Set found = rngAM.Find(cell.Value)
' If still not found, copy to the value to the 'Unmatched Parts' sheet
If found Is Nothing Then
ThisWorkbook.Worksheets("UnmatchedPartNo").Range("A" & lastRowUMPN + 1).Value = cell.Value
MsgBox "I have found a value " & cell.Value & " that did not exist in any sheets."
End If
End If
End If
' Reset 'found' to equal nothing for the next loop
Set found = Nothing
Next
End Sub
Here's a sub that takes 2 parameters;
A cell that has the value to search for, and a number indicating the sheet to search in.
When the sub doesn't find the value in neither of the sheets, it adds a new sheet "Unmatched Part No" if it doesn't exist and adds the value that's not found in column A in that sheet:
Sub searchSheet(ByVal searchFor As Range, sheetNum As Integer)
Dim sheetsArr As Variant
sheetsArr = Array("Active_Buy", "Active_Others", "Active_Make", "Unmatched Part No") 'You can change the names of your sheets here
If sheetNum = 3 Then 'When we reach the last sheet in our array, then we haven't find a match in neither of the previous sheets
Dim ws As Worksheet, wsExist As Boolean, lastRow As Integer
wsExist = False
'Check if the sheet "Unmatched Part No" exists
For Each ws In Worksheets
If ws.Name = sheetsArr(3) Then
wsExist = True
Exit For
End If
Next ws
'If the sheet "Unmatched Part No" doesn't exist add one with this name
If Not (wsExist) Then ThisWorkbook.Sheets.Add(after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)).Name = sheetsArr(3)
lastRow = ThisWorkbook.Sheets(sheetsArr(3)).Cells(Rows.Count, "A").End(xlUp).Row 'last used row in column A in the unmatched sheet
ThisWorkbook.Sheets(sheetsArr(3)).Range("A" & lastRow + 1).Value2 = searchFor.Value2 'append the unfound value in column A
'MsgBox "New value" & searchFor.Value2 & "appended to 'Unmatched Part No' A" & lastRow + 1
Exit Sub
End If
Dim search 'Search should be of a variant type to accept errors given by the match function
search = Application.Match(searchFor.Value2, ThisWorkbook.Sheets(sheetsArr(sheetNum)).Range("A:A"), 0)
If IsError(search) Then searchSheet searchFor, sheetNum + 1 'When match doesn't find the searchFor value, Search is an #N/A error, then search in the next sheet
End Sub
And you need another sub to call the first one passing each cell of column K of filter sheet to the first sub. Here it is:
Sub lookInSheets()
Dim lastRw As Integer, ctrlCol As Range
lastRw = ThisWorkbook.Sheets("filter").Cells(Rows.Count, "K").End(xlUp).Row 'To abbreviate the search to just the filled cells in column K
Set ctrlCol = ThisWorkbook.Sheets("filter").Range("K1:K" & lastRw)
For Each ctrlCell In ctrlCol
searchSheet ctrlCell, 0
Next ctrlCell
End Sub
Copy both subs in a new module and run the second one to achieve your goal.

Locate a cell using 2 values in a VBA form

My input form contains 2 texts which corresponds to a specific row & column header of my worksheet. I want to use the 2 selected texts in the form to locate the cell, and edit the respective cell's value.
1 of the value is part of an array in a Listbox (e.g. located in ListBox2.Column(0,1))
The other value is from a combo box (e.g. cmbName).
How can I use these 2 values to locate the cell? I thought maybe index/match will work, but it seems all too complicated.. any help will be appreciated - thanks!
I tried doing a double for loop to locate the column, but I can't figured out how to locate the right row.
For m=27 To finalcol
For n = 0 to ListBox2.ListCount - 1
If ListBox2.Column(0,n) = Trim(ThisWorkBook.Worksheets("Masterlist").Cells(1,m).Text) Then
MsgBox ("Matched!")
End If
Next n
Next m
I get the "Matched!" output, but I'm not sure how to achieve the next step. Is this approach fundamentally limited?
First you can find the row corresponding to cmbName, and then the column as you already did:
' Find the row corresponding to cmbName
For r=2 To ThisWorkBook.Worksheets("Masterlist").UsedRange.Rows.Count
If cmbName = Trim(ThisWorkBook.Worksheets("Masterlist").Cells(r,1).Text)
therow=r
End if
Next r
' Find the column corresponding to ListBox2 column 0:
For m=27 To finalcol
For n = 0 to ListBox2.ListCount - 1
If ListBox2.Column(0,n) = Trim(ThisWorkBook.Worksheets("Masterlist").Cells(1,m).Text) Then
If ListBox2.Selected(n)
ThisWorkBook.Worksheets("Masterlist").Cells(therow,m).Text = ListBox2.Column(1,n)
End If
End If
Next n
Next m
If you want to use the double for loop it would be something like:
Public Sub Test
'Loops through all items in Listbox2'
For n = 0 to ListBox2.ListCount - 1
FindCell ListBox2.List(n)
Next
End Sub
Private Sub FindCell (lstValue As String)
'Sets the ws As a variable we can use'
Dim ws as Worksheet
Set ws = ThisWorkBook.Worksheets("Masterlist")
Dim ColumnLetter as String
'Find the last non-blank cell in row 1
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
'Loops through each cell in Row 1'
For Each cell In ws.Range("A1:A" & lCol)
If cell.Value = lstValue Then 'Checks if the cell value is equal to the item we passed in from the ListBox'
ColumnLetter = Split(Cells(1, cell.Column).Address, "$")(1) 'To use Worksheet.Range below, we need to find the column letter'
'Find the last non-blank cell in column A(1)
lRow = Cells(Rows.Count, cell.Column).End(xlUp).Row 'Goes from the bottom of the file up to the first cell that contains a value and stores the row # as a variable'
For Each cellCol in ws.Range(ColumnLetter & "2:" ColumnLetter & lRow) 'Now we need to check each cell in the row for the value in the combo box'
If cellCol.Value = cmbName.Value Then
Messagebox ("Matched")
End If
Next
End If
Next
End Sub
Let me know how this goes :)
You can try this.
I dummied up a worksheet that looks like this ...
... I then added a named range to that matrix called rngDataSet.
Then, using this code, it demonstrates logic that will ultimately find and select the relevant cell based on the row and column headings you provide. You should be able to adapt this code to your own logic.
Public Sub FindCell(ByVal rngDataSet As Range, ByVal strRowHeader As String, ByVal strColHeader As String, ByVal varNewValue As Variant)
Dim objCell As Range, objColCell As Range, objRowCell As Range
' Find the column header
For Each objCell In rngDataSet.Rows(1).Cells
If UCase(Trim(objCell.Text)) = UCase(Trim(strColHeader)) Then
Set objColCell = objCell
Exit For
End If
Next
' Find the row header
For Each objCell In rngDataSet.Columns(1).Cells
If UCase(Trim(objCell.Text)) = UCase(Trim(strRowHeader)) Then
Set objRowCell = objCell
Exit For
End If
Next
If objColCell Is Nothing Or objRowCell Is Nothing Then
MsgBox "Either 1 or both of the supplied headers were not found.", vbCritical, "Error"
Else
rngDataSet.Worksheet.Cells(objRowCell.Row, objColCell.Column) = varNewValue
End If
End Sub
Public Sub DoFindCell()
Dim strRowHeader As String, strColHeader As String
strRowHeader = InputBox("Row Header ...", "Row Header", "Row Header ")
strColHeader = InputBox("Column Header ...", "Column Header", "Col Header ")
FindCell Sheet1.Range("rngDataSet"), strRowHeader, strColHeader, “New Value”
End Sub
I hope that helps.
"DoFindCell" only exists to invoke the logic, that should be replaced by your own list/combo box values.

Iteration through column to find a particular value

I am trying to go through a column of empty cells in my excel spreadsheet in order to find the row in which the word "Yes" is found. Afterwards, upon finding the word in a particular row, for instance in cell D23, I want it to go over one column to cell E23 and paste the value in that cell into cell B100. Here is what I have so far, but it doesn't seem to be functioning correctly:
Sub Test3()
Dim x As String
x = "Yes"
' Dim found As Boolean
' Select first line of data.
Range("D4").Select
' Set search variable value.
' Set Boolean variable "found" to false.
found = False
' Set Do loop to stop at empty cell.
Do Until ActiveCell.Value = x
' Check active cell for search value.
If ActiveCell.Value = x Then
Range("B100").Value = ActiveCell.Offset(0, 1).Value
found = True
Exit Do
End If
' Step down 1 row from present location.
ActiveCell.Offset(1, 0).Select
Loop
' Check for found.
If found = True Then
MsgBox "Value found in cell " & ActiveCell.Address
Else
MsgBox "Value not found"
End If
End Sub
Thanks!
As #tigeravatar mentioned in his comment, you'd probably be better off using Excel's native functions, but, if you want to do this via VBA, you can do it much more easily and efficiently using the Find function which returns a range if found or else 'Nothing' if not.
Using that, you can test to see what you got back. Try this:
Sub Test3()
Dim x As String
Dim rng As Range
x = "Yes"
Set rng = Range("D4:D10000").Find(x)
If Not rng Is Nothing Then
Range("B100").Value = rng.Offset(0, 1).Value
MsgBox "Value found in cell " & rng.Address
Else
MsgBox "Value not found"
End If
End Sub
Hope it does the trick.

Comparing two excelsheets for uncommon records based on common 'id' field(Column)

I am comparing two excelsheets in the same workbook.
I want to check whether the records from sheet1 are exactly same as records in sheet2 based on common Question_id(Column A of both worksheets)
This question_id(column A) has values such as
1
1a
1a.1
1a.1a
1a.1b
1a.1c
2
2a
2a.1
2a.1a
2a.1b
2a.1c etc....
I want to compare the records based on this Question_id(Column A Value).
If Question_id is same and records(the remaining row) are not same then am coloring those records in red background(only specific cells and not the whole row)
For the same, I have following code.
Sub RunCompare()
Call compareSheets("Sheet1", "Sheet2")
End Sub
Sub compareSheets(shtSheet1 As String, shtSheet2 As String)
Dim mycell As Range
Dim mydiffs As Integer
Application.ScreenUpdating = false
'Color Uncommon records in Red Background
For Each mycell In ActiveWorkbook.Worksheets(shtSheet2).UsedRange
If Not mycell.Value = ActiveWorkbook.Worksheets(shtSheet1).Cells(mycell.Row, mycell.Column).Value Then
mycell.Interior.Color = vbRed
mydiffs = mydiffs + 1
End If
Next
'Display no. of differences
MsgBox mydiffs & " differences found", vbInformation
ActiveWorkbook.Sheets(shtSheet2).Select
MsgBox "Data Scrubbed Successfully..."
Application.ScreenUpdating = True
End Sub
The above code runs fine when I have same sequence of Question_id (and therefore of records) in both the excelsheets.
Assume I have different sequence of Question_id (and therefore of records) in both the sheets.
Then how I can achieve this...?
Something Like using where clause in my code Where Sheet1.Question_id = Sheet2.Question_id
i.e. I'll pick up question_id and the full row from sheet1 and I will compare it against records in sheet2 based on matching Question_id(value of Column A) only.
Can someone tell where I can put the condition and what type of condition so that, even if both the excelsheets have random sequences of Question_id; I will be able to compare the records from sheet1 and sheet2.
EDIT: on 23rd March 2015
I have changed the code using find() method instead of loops as below:
Still I havn't arrived at my solution.
Here am trying to list Question_Ids of all non-matching rows from sheet2 in sheet3 - Column A.
Option Explicit
Sub test()
Dim rng As Range, c As Range, cfind As Range, mycell As Range, cfindRow As Range
On Error Resume Next
Worksheets("Sheet3").Cells.Clear
With Worksheets("Sheet2")
Set rng = .Range(.Range("A2"), .Range("a2").End(xlDown))
For Each c In rng
With Worksheets("Sheet1")
Set cfind = .Columns("A:A").Cells.Find _
(what:=c.Value, lookat:=xlWhole)
'Find method always returns Range; So the following line should be something If cfind is not Nothing OR cfind <> Nothing (Both the syntaxes are wrong. Suggest me the right syntax please.
If cfind = 1 Then
'Here please tell me how to reference a whole row based on Column A value
'Here using cfind and again using mycell is something wrong as mycell variable again compares rows in sheet2 with rows in sheet1 which include Question_Id too.
Set mycell = ActiveWorkbook.Worksheets("Sheet2").UsedRange.End(xlDown)
'My both the excelsheets have values from columns A to AD. Still I want to make the code for all used Ranges of columns instead of only A to AD.
Set cfindRow = Worksheets("Sheet1").Rows("A2:AD").Cells.Find _
(what:=mycell.Value, lookat:=xlWhole)
'Find method always returns Range; So the following line should be something If cfindRow is not Nothing OR cfindRow <> Nothing (Both the syntaxes are wrong. Suggest me the right syntax please.
If cfindRow = 1 Then
'MsgBox "Match Found" 'Right Now do Nothing
End If
Else
' mycell.Interior.Color = vbRed
' mydiffs = mydiffs + 1
'Copy the question numbers to sheet3 either if they are new in new sheet (Sheet2) or content against them (in the whole row-any column value) is changed.
cfind.Copy Worksheets("sheet3").Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
End If
End With
Next c
Application.CutCopyMode = False
End With
MsgBox "Data Scrubbed Successfully..."
End Sub
Can someone tell me how to refer those ranges based on key column values?
My new approach towards solution:
(It may be a hint to give me answer on how to reference Row values based on key column)
Getting row indices of both the sheets; column A values
(Question_Id's) i.e.
c.Row and cfind.Row
Then
Check If(Sheet2.Cells(c.Row, Columns) = Sheet1.Cells(cfind.Row,
Columns) (To compare columns against matching Question_Ids only.)
So Finally this what all am trying to achieve :
1)Compare two sheets based on key column:
Pick up the Question_Id from Sheet2 - column A and compare it against column A in Sheet1. If the key columns from both the sheets match and also the contents against them(the complete row) matches- then Do nothing.
If the key column value(Question_Id - Column A) matches but values(Row) against it do not match them color those specific cells (Only cells) and not the whole row in Red background.
The Question_Id's which are there in sheet2 but not in sheet1 should be listed under first column in sheet3. Starting from A2.
The Question_Id's which are there in sheet1 but not in sheet2 should be listed under second column in sheet3. Starting from B2.
I am basing my code off of your first approach, because I found it simpler and more readable than the second approach.
We'll just do the most naive algorithm, which is to iterate through every row in the used range of both worksheets. (The fastest algorithm would probably be to sort both ranges in memory and then compare, but simplicity of code over performance optimization for now.)
Sub compareSheets(shtSheet1 As String, shtSheet2 As String)
Dim range1 As Range, range2 as Range
Dim mydiffs As Integer, row1 As Integer, row2 As Integer, col As Integer
Application.ScreenUpdating = False
'First create the two ranges we will be using
Set range1 = ActiveWorkbook.Worksheets(shtSheet1).UsedRange
Set range2 = ActiveWorkbook.Worksheets(shtSheet2).UsedRange
'Iterate through the rows of both ranges
For row1 = 1 To range1.Rows.Count
For row2 = 1 To range2.Rows.Count
'Only process the ranges if they share a common key in column 1
If range1.Cells(row1, 1) = range2.Cells(row2, 1) Then
'If they share the same key, iterate through columns and compare
For col = 1 To WorksheetFunction.Max(range1.Columns.Count, range2.Columns.Count)
If Not range1.Cells(row1, col).Value = range2.Cells(row2, col).Value Then
range1.Cells(row1, col).Interior.Color = vbRed
range2.Cells(row2, col).Interior.Color = vbRed
mydiffs = mydiffs + 1
End If
Next
End If
Next
Next
'Display no. of differences
MsgBox mydiffs & " differences found", vbInformation
Application.ScreenUpdating = True
End Sub
There are some specifications I wasn't sure of. For example, what if a key is in one spreadsheet but not the other? Should it be colored red in the sheet where it exists?
Nevertheless, I think the above code should give you a good start to address your more conceptual questions, and I'm happy to help adjust as needed, so please comment if there are specific requirements I'm missing.
Update 1
Here's the update code after our discussion in chat (link in comments), which takes the unmatched keys from the full outer join and copies them to a third sheet.
Sub compareSheets(shtSheet1 As String, shtSheet2 As String, shtSheet3 As String)
Application.ScreenUpdating = False
Dim range1 As Range, range2 As Range
Dim myDiffs As Integer, row1 As Integer, row2 As Integer, col As Integer
Dim sheet3index1 As Integer, sheet3index2 As Integer, i As Integer
Dim leftKeyMatched As Boolean 'Boolean to keep track of whether the key in sheet1 has a match as we are looping
Dim rightKeysMatched() As Boolean 'Array to keep track of which keys in sheet2 have matches
Set range1 = ActiveWorkbook.Worksheets(shtSheet1).UsedRange
Set range2 = ActiveWorkbook.Worksheets(shtSheet2).UsedRange
ReDim rightKeysMatched(range2.Rows.Count)
For row1 = 1 To range1.Rows.Count
leftKeyMatched = False
For row2 = 1 To range2.Rows.Count
If range1.Cells(row1, 1) = range2.Cells(row2, 1) Then
'We have a match, so mark both sides as matched
leftKeyMatched = True
rightKeysMatched(row2 - 1) = True 'This -1 is because the array indexing starts at 0 but the rows in the spreadsheet start at 1
For col = 1 To WorksheetFunction.Max(range1.Columns.Count, range2.Columns.Count)
If Not range1.Cells(row1, col).Value = range2.Cells(row2, col).Value Then
range1.Cells(row1, col).Interior.Color = vbRed
range2.Cells(row2, col).Interior.Color = vbRed
myDiffs = myDiffs + 1
End If
Next
End If
Next
'Print out the key from sheet1 if it didn't find a match in sheet2
If leftKeyMatched = False Then
sheet3index1 = sheet3index1 + 1
ActiveWorkbook.Worksheets(shtSheet3).Cells(sheet3index1, 1) = range1.Cells(row1, 1)
End If
Next
'Now print out any key that still hasn't been matched in sheet2
For i = 0 To range2.Rows.Count
If rightKeysMatched(i) = False Then
sheet3index2 = sheet3index2 + 1
ActiveWorkbook.Worksheets(shtSheet3).Cells(sheet3index2, 2) = range2.Cells(i + 1, 1) '+1 for same reason as above, index starts at 0 versus 1
End If
Next
'Display no. of differences
'MsgBox myDiffs & " differences found", vbInformation
Application.ScreenUpdating = True
End Sub
I'll take a crack at this
Sub compareSheets(shtSheet1 As String, shtSheet2 As String)
Dim mycell As Range
Dim mydiffs As Integer
Dim ws1 as WorkSheet
Dim ws2 as WorkSheet
Dim rng as Range
Dim SourceRow as integer
Dim Col as integer
set ws1 = ActiveWorkbook.Worksheets(shtSheet1)
set ws2 = ActiveWorkbook.Worksheets(shtSheet2)
myDiffs = 0
'Application.ScreenUpdating = false 'enable this later, once it's all working
'Color Uncommon records in Red Background
'your key is in column A, so we'll only loop through that column
For sourceRow = 1 to ws2.usedrange.Rows.Count
set rng = ws1.range(ws1.address).find(what:=ws2.cells(sourcerow, 1), LookIn:=xlValues, _
LookAt=xlWhole, MatchCase:=False)
'making an assumption on MatchCase, change as needed
if not rng is Nothing then 'we found the key, now let's look at the rest of the row
col = 2
'loop through the rest of the columns for this row
while col < ws2.usedRange.Columns.Count
'if the cell in the row we just found on sheet1 <> the cell that we were looking for from sheet2
if rng.cells(1,col) <> ws2.cells(sourcerow,col) then
rng.cells(1,col).Interior.Color = vbRed
mydiffs = mydiffs+1
end if
col = col + 1
wend
else
'we didn't find the key. pop up a msgbox. you may want something else
MsgBox ("Sheet2 key: " & ws1.value & " not found on Sheet1")
end if
'Display no. of differences
MsgBox mydiffs & " differences found", vbInformation
ActiveWorkbook.Sheets(shtSheet2).Select
MsgBox "Data Scrubbed Successfully..."
Application.ScreenUpdating = True
End Sub
If you want to find a value in a range use the following:
.Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)
Like this :
Application.ScreenUpdating = False
'On Error Resume Next 'Err.Numbers 9, 91 => Find: value not found
Dim findCell as range
ActiveWorkbook.Worksheets(shtSheet2).Select
ActiveWorkbook.Worksheets(shtSheet2).UsedRange.Select
'Color Uncommon records in Red Background
For Each mycell In ActiveWorkbook.Worksheets(shtSheet1).UsedRange
Set findCell = Selection.Find(What:=Trim(mycell.value & ""), LookIn:=xlValues)
If findCell Is Nothing Then
mycell.Interior.Color = vbRed
mydiffs = mydiffs + 1
End If
Next
Note :
Please change Application.ScreenUpdating = True to Application.ScreenUpdating = False
And for more information use this MSDN article
And for using a function like that you want:
Public Function look_up_id (r as Range) As Variant
'
'Function body
'
End Function
'....
Call look_up_id(ActiveWorkbook.Worksheets(shtSheet2).Range("A:A", table))
'....

Resources