Autopopulate a column utilizing the MATCH function - vba

I have 2 workbooks: "MainWorkbook.xlsm" and "ReferenceWorkbook.xlsx". The reference workbook is a report that the main workbook pulls data from.
There is a column in my main workbook called "Vendor Name", which is column J. The column in the reference workbook that "Vendor Name" would be referencing is column X, named "Vendor_Data". Both of the vendor columns in the 2 worksheets are non-numeric data types. Furthermore, both of these worksheets are subject to variations in row counts; I may have 200 rows in "Mainworkbook.xlsm" one day and 230 the next. The same applies for "ReferenceWorkbook". The vendor column in "MainWorkbook.xlsm" will remain static as far as it's index value goes, but the position of the vendor column in ReferenceWorkbook.xlsx could potentially change in the future (ex. going from column x to column y). The header row in "MainWorkbook") is row 2, while the header row in "ReferenceWorkbook" is row 1.
What I would like to do is build a macro that will automatically populate my vendor column in "MainWorkbook" by first matching to the vendor column in "ReferenceWorkbook" based on their headers and then matching rows by their primary keys (Column C in "MainWorkbook" and column K in "ReferenceWorkbook"). The primary key column in "ReferenceWorkbook" is also subject to having it's column index changed, like it's vendor column, so I would like to do all of my header matching based on header names, not their index values.
Since I'm just starting out with VBA, the best I have so far is an incomplete and very logically flawed block of code:
Sub New_Macro()
Dim ran As Range, source_header As Range, target_header As Range
Dim source As Workbook, source_sheet As Worksheet, target As Workbook, target_sheet As Worksheet
Dim i As Integer, j As Integer, Match_header As Integer
Set source = Application.Workbooks("ReferenceWorkbook.xlsx")
Set Reference_sheet = source.Worksheets("ReferenceSheet")
Set target = Application.Workbooks("MainWorkbook.xlsm")
Set target_sheet = target.Worksheets("MainSheet")
Set source_worksheet_header = source_sheet.Range("X1")
Set target_worksheet_header = target_sheet.Range("J2")
LR = target_sheet.Cells(Rows.Count, 1).End(xlUp).Row
j = 10
Set ran = target_sheet.Range("J3" & LR)
ran.ClearContents
Do While j < 11
For Each cell In target_worksheet_header
For i = 3 To LR
Match_header = source_worksheet_header.Find(cell.Value)
target_sheet.Cells(i, j).Value = Application.WorksheetFunction.Index(source_sheet.Range("X"), WorksheetFunction.Match(target_sheet.Cells(i, 10).Value, source_sheet.Range("X"), LR), Match_header)
On Error Resume Next
Next i
j = j + 1
Next cell
Loop
End Sub
Does anyone have a way to turn this into an actual solution? Any help would be wonderous

Compiled but not tested:
Sub New_Macro()
Dim ran As Range, c As Range
Dim source_sheet As Worksheet
Dim target_sheet As Worksheet
Dim srcVendorCol As Range, srcIdCol As Range, f As Range
Dim vndr, r, id
Dim LR As Long
Set source_sheet = Workbooks("ReferenceWorkbook.xlsx") _
.Worksheets("ReferenceSheet")
Set target_sheet = Workbooks("MainWorkbook.xlsm") _
.Worksheets("MainSheet")
Set f = source_sheet.Rows(1).Find(what:="Vendor_Data", _
lookat:=xlWhole, LookIn:=xlValues)
If Not f Is Nothing Then
Set srcVendorCol = f.EntireColumn
End If
Set f = Nothing
Set f = source_sheet.Rows(1).Find(what:="PrimaryKey", _
lookat:=xlWhole, LookIn:=xlValues)
If Not f Is Nothing Then
Set srcIdCol = f.EntireColumn
End If
If srcVendorCol Is Nothing Or srcIdCol Is Nothing Then
MsgBox "Required column headers not found in source sheet!"
Exit Sub
End If
'find last populated cell in Col J
LR = target_sheet.Cells(Rows.Count, "J").End(xlUp).Row 'EDIT
Set ran = target_sheet.Range("J3:J" & LR)
For Each c In ran.Cells
id = c.EntireRow.Cells(3).Value
If Len(id) > 0 Then 'EDIT - added check for Id length
r = Application.Match(id, srcIdCol, 0)
If Not IsError(r) Then
c.Value = Application.Index(srcVendorCol, r, 1)
Else
c.Value = "Id not found"
End If
End If
Next c
End Sub

Related

VBA. Replace a table cell content based on match from another table or delete entire row if match is not found

I am trying to make the following to work:
There are two tables in a separate worksheets. I want it to check each cell in worksheet2 column B and find a match from worksheet1 column A. If a match is found then replace the data in worksheet2 column B with a data from a matching row of worksheet1 column B.
If a match is not found from a worksheet1 column A then delete entire row in a worksheet2 column B.
Sub match_repl_del()
Dim r1 As Long, rfound, vfound
Dim w1, w2, v As Long
Set w1 = Sheets(3) ' data sheet
Set w2 = Sheets(2) ' target sheet
r1 = 2 'data starting from row 2
Do While Not IsEmpty(w1.Cells(r1, 1))
v = w1.Cells(r1, 1)
rfound = Application.Match(v, w2.Columns(2), 0) ' look for value
If Not IsError(rfound) Then ' found it?
vfound = w2.Cells(rfound, 2)
If w1.Cells(r1, 2) <> vfound Then ' if value does not match sheet1 column b
w2.Cells(rfound, 2) = w1.Cells(r1, 2) ' update based on origin sheet
lastC = w2.Cells(rfound, 1).End(xlToRight).Column
w2.Range(w2.Cells(rfound, 1), w2.Cells(rfound, lastC)).Interior.ColorIndex = 5
Else ' delete entire row on sheet2 if match is not found
w2.Rows(r1).EntireRow.Delete
End If
End If
r1 = r1 + 1
Loop
End Sub
Try this wat, it's work for me :
Option Explicit
Sub test()
' Active workbook
Dim wb As Workbook
Set wb = ThisWorkbook
Dim i As Long
Dim j As Long
'*******************************************
'Adapt this vars
'define your sheets
Dim ws_1 As Worksheet
Dim ws_2 As Worksheet
Set ws_1 = wb.Sheets("Sheet1") 'find a match in worksheet1 column A
Set ws_2 = wb.Sheets("sheet2") 'cell in worksheet2 column B
'definie the last Rows
Dim lastRow_ws1 As Long
Dim lastRow_ws2 As Long
lastRow_ws1 = ws_1.Range("A" & Rows.Count).End(xlUp).Row 'if you need, adjust column to find last row
lastRow_ws2 = ws_2.Range("B" & Rows.Count).End(xlUp).Row 'if you need, adjust column to find last row
'*******************************************
For i = lastRow_ws2 To 2 Step -1
For j = 1 To lastRow_ws1
Dim keySearch As String
Dim keyFind As String
keySearch = ws_2.Cells(i, 2).Value
keyFind = ws_1.Cells(j, 1).Value
If keySearch = keyFind Then
'MsgBox keySearch & " " & keyFind & " yes"
ws_2.Cells(i, 2).Value = ws_1.Cells(j, 2).Value
GoTo next_i
End If
Next j
ws_2.Rows(i).EntireRow.Delete
next_i:
Next i
End Sub

Select cells that fit in the range of the counter and concatenate what is selected from the range

I've been working on a Macro that i need to copy, concatenate what has been selected through the counter. e.g. is below
excel snapshot example
so what i want to do is set a count in column c from 1 to "infinite" because each worksheet varies to go up to 10 or hundreds and when the counter hits a value of 1 again to stop concatenate column D what is in the range from 1 to "the last digit it stopped before hitting 1 again" and paste it on a different sheet. I know little to nothing on VBA but I understand the copy and paste to different sheet part. I'm just stuck on the counter and the concatenate part. Here is the code i have so far(i edited it to resemble the example for better reference)
'select counter/concatenate
Sheets(1).Select
Columns("C").EntireColumn
Do
Columns("C").Count
For i = 1 To 9999
Loop While (i <= 1)
If i = 1 Then
select.columns("D")
after the count is where i am stuck. this count is what I've come up with looking at different variations of counters.
I suggest you Forget about column and use just one cell for easier understanding. A cell is a reference that allows you to refer to any other cells on the sheet by using Offsets. You may use two Loops, the outer one crawling the columns, the inner one working downward until it finds 1
Dim i As Long ' note that in VBA integer Overflows at 65535 rows
Dim s As String
Set aCell = Worksheet("Sheet1").Range("D1")
While aCell.Column < 255
i = 0
s = ""
While Not aCell.Offset(i, 0).Value = 1
s = s & aCell.Offset(1, 0).Value
Wend
' paste s somewhere by using range.value = s
Set aCell = aCell.Offset(0, 1)
Wend
By specifying the workbook and worksheet before the range, you may refer to the proper cell without being dependent on the active worksheet or range.
Hope this works for you.
You can try this (not tested):
Dim s As String, firstAddr as String
Dim f as range, iniCell As Range
With Worksheet("MySheet") '<--| change "MySheet" to your actual sheet name
With .Range("C1", .Cells(.Rows.Count, 3).End(xlUp))
Set f = .Find(What:=1, LookAt:=xlWhole, LookIn:=xlValues, After:=.Cells(.Rows.Count, 1))
If Not f Is Nothing Then
firstAddr = f.Address
Set iniCell = f
Set f = FindNext(f)
Do While f.Address <> firstAddr
s = s & Join(Range(iniCell, f.Offset(-1)).Offset(, 1), "")
' here code to paste s somewhere
Set iniCell = f
Set f = FindNext(f)
Loop
End If
End With
End With
Here's one I actually tested, using some random data in columns C and D.
You'll have to modify a little to get exactly where you want the data to go, but should get you in the right direction.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim i As Long
Dim s As String
Dim lastRow As Long
Dim c As Integer
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Set ws1 = ThisWorkbook.Sheets("Sheet1")
Set ws2 = ThisWorkbook.Sheets("Sheet2")
lastRow = ws1.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row
'This will get an accurate last row
c = 1
For i = 1 To lastRow
s = s & ws1.Cells(i, 4).Value 'Build the string
If ws1.Cells(i + 1, 3).Value = 1 Or ws1.Cells(i + 1, 3).Value = "" Then
ws2.Cells(c, 1).Value = s
s = ""
c = c + 1
'If the next cell to check is 1 or blank, then copy the values to the next cell in order on sheet2
End If
Next
End Sub
Walking through it, lastRow is set using the last row in the sheet with a value in it. Then, c is set to one, although you could set this to the last available row in ws2 using the same process. After that it just steps through the rows from 1 To LastRow building strings and transferring the value to ws2 when it's about to hit a 1.

Excel VBA Macro: Iterating over values on one page to check for match on another page and assign value

What I want to do: Iterate over values on one page to check for match on another page and if a match is found take a value from 2nd page same row but different column.
I've been trying now for quite some time. I'm new to VBA-scripting / Excel and might be approaching the problem incorrectly, hence why I'm asking here!
My code so far:
Sub InsertData()
ScreenUpdating = False
Dim wks As Worksheet
Dim subSheet As Worksheet
Set subSheet = Sheets("Sheet4")
Dim rowRangeSub As Range
Dim LastRowSub As Long
LastRowSub = subSheet.Cells(subSheet.Rows.Count, "C").End(xlUp).Row
Set rowRangeSub = subSheet.Range("C2:C" & LastRowSub)
Dim subGroupList As ListObject
Dim rowRange As Range
Dim colRange As Range
Dim LastCol As Long
Dim LastRow As Long
Dim Found As Range
'START OF SHEET1'
Set wks = Sheets("SHEET1")
LastRow = wks.Cells(wks.Rows.Count, "B").End(xlUp).Row
Set rowRange = wks.Range("B2:B" & LastRow)
'Loop through each row in B column (Names)'
For Each rrow In rowRange
If Not IsEmpty(rrow) Then
With Sheets("Sheet4").Range("C2:C" & LastRowSub)
Set Found = .Find(What:=rrow, _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Found Is Nothing Then
'Debug.Print "Found"'
wks.Cells(rrow.Row, "K").Value = "Found"
Else
wks.Cells(rrow.Row, "K").Value = "Not Found"
'Debug.Print "Not Found"'
End If
End With
End If
Next rrow
'END OF SHEET1'
'START OF SHEET2'
Set wks = Sheets("SHEET2")
LastRow = wks.Cells(wks.Rows.Count, "B").End(xlUp).Row
Set rowRange = wks.Range("B2:B" & LastRow)
'END OF SHEET2'
'START OF SHEET3'
Set wks = Sheets("SHEET3")
LastRow = wks.Cells(wks.Rows.Count, "B").End(xlUp).Row
Set rowRange = wks.Range("B2:B" & LastRow)
'END OF SHEET3'
ScreenUpdating = True
End Sub
The setup in the Excel file is as such:
The three sheets, Sheet1, Sheet2, Sheet3 contains a lot of data in its 10 first columns (A-J) and the 11th column (K) is where the data is to be inserted if it is found. Pertinent data, names, is found in column B where B:1 is just "Name" as a title. There is also some empty cells in the column to take into consideration.
The 4th sheet, Sheet4 contains some data in its 5 first columns. The names which are to be matched can be found in column C, and if a match is found it is supposed to collect data from the Cells(Found.Row, "E") where "E" is column E.
This problem has been screwing with my head quite a lot since .Find()-function seems to not work as I expect it to, as in it finds the opposites sometimes.
My main question is: How do I assign the correct value to the row?
wks.Cells(rrow.Row, "K").Value = rowRangeSub.Cells(Found.Row, "E").Value
I feel like I've tested at least 10 different ways to assign, but I keep on getting error after error. Most of the time it's a missmatch error.
Any help is appreciated!
EDIT since reading comments:
Ok, here it goes :
All columns are formatted as text.
Column A: Personal numbers: not relevant
Column B: Names: Form is: Lastname, Firstname. This is to be used when searching for a match.
Column C to J not relevant with various information about a person.
Column K: This columns cell starts out empty. This is to be filled by the macro.
I have three different books within the Excel file that have data that looks like what I've explained, just different data in each book.
The 4th book is as such:
Column A and B is not relevant with info not needed at all.
Column C: Is the names in form Lastname, Firstname. This is what should be the column cells to compare with column B's cells in the other books.
Column D: Not relevant
Column E: This is the important part of Sheet4. For every person there is a "group number" that can be found in this column for every row.
What I want to do is compare each cell in column B in Sheet1-3 for a match in column C in Sheet4. If a match is found (not all are assigned a group, so matches might not be found) then take cell information from Sheet4 on the row which a match was found and column "E", put this information in the row in Sheet1-3 and column "K".
Example data (is there a way to submit tables?):
Sheet1:
COLUMN B
Tablesson, Pen
Paper, Ink
Eraser, Screen
COLUMN K is at this moment empty
Sheet4:
COLUMN C
Paper, Ink
Eraser, Screen
COLUMN E
55
77
RUNS THE MACRO, Sheet1 after macro:
COLUMN B
Tablesson, Pen
Paper, Ink
Eraser, Screen
COLUMN K
[First entry is empty since no match was found]
55
77
Hopefully this is understandable!
I simplified the process by using a Scripting Dictionary.
Sub InsertData()
Dim lastRow As Long, x As Long
Dim dicNames, k As String, v As Variant
Set dicNames = CreateObject("scripting.dictionary")
'Create list of Names to compare against and values to update
With Worksheets("Sheet4")
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
For x = 2 To lastRow
k = .Cells(x, 3).Value 'Name from Column C
v = .Cells(x, 5).Value 'Value From Column E
'Add Key Value pairs to Dictionary
If Not dicNames.Exists(k) Then dicNames.Add k, v
Next
End With
ProcessWorksheet Worksheets("Sheet1"), dicNames
ProcessWorksheet Worksheets("Sheet2"), dicNames
ProcessWorksheet Worksheets("Sheet3"), dicNames
End Sub
Sub ProcessWorksheet(ws As Worksheet, ByRef dicNames)
Dim k As String, v As Range
Dim lastRow As Long, x As Long
With ws
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
For x = 2 To lastRow
k = .Cells(x, 2) 'If Name from Column B
If dicNames.Exists(k) Then
.Cells(x, 11) = dicNames(k) 'Then Column K = Value from Sheet4
End If
Next
End With
End Sub
Sub InsertData()
Dim lastRow As Long, x As Long
Dim dicNames, k As String, v As Variant
Set dicNames = CreateObject("scripting.dictionary")
'Create list of Names to compare against and values to update
With Worksheets("Sheet4")
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
For x = 2 To lastRow
k = .Cells(x, 3).Value 'Name from Column C
v = .Cells(x, 5).Value 'Value From Column E
'Add Key Value pairs to Dictionary
If Not dicNames.Exists(k) Then dicNames.Add k, v
Next
End With
ProcessWorksheet Worksheets("Sheet1"), dicNames
ProcessWorksheet Worksheets("Sheet2"), dicNames
ProcessWorksheet Worksheets("Sheet3"), dicNames
End Sub
Sub ProcessWorksheet(ws As Worksheet, ByRef dicNames)
Dim k As String, v As Range
Dim lastRow As Long, x As Long
With ws
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
For x = 2 To lastRow
k = .Cells(x, 2) 'If Name from Column B
If dicNames.Exists(k) Then
.Cells(x, 11) = dicNames(k) 'Then Column K = Value from Sheet4
End If
Next
End With
End Sub
Basically used the code provided by Thomas Inzina with minor changes:
If dicNames.Exists(k) Then
newV = IIf(dicNames(k) = v, v, dicNames(k) & "," & v)
dicNames.Remove (k)
dicNames.Add k, newV
Else
dicNames.Add k, v
End If
This takes duplicates into consideration.
I also used this cleaning function since I couldn't find the built-in one in VBA. Used them as such:
k = CleanTrim(.Cells(X, 3).Value) 'Name from Column C
k = CleanTrim(.Cells(X, 2).Value) 'If Name from Column B

Excel-VBA: Merging columns with split data where headers differs by one specific character

I am setting up a workbook that imports and sorts data without the need of manual operations.
Some of the data that needs to be imported contains data split in two columns where the headers differ by one character. I've uploaded an example here:
Example sheet
The headers with the split data are "11, 0-3-1m Jord" and "11, 0-3-1m. Jord" where the difference is the dot. The variable part of the header between sheets to be imported is the "11, 0-3-1m" with or without a dot as that is a name of a sample that the is user defined. "Jord" is a constant as it categorize the sample as a dirt sample and will not change between sheets to be imported. The first row of data (row 7) contains duplicate data for "Torrstoff" in the split columns where one of them needs to be deleted together with the empty rows when merging.
So, does this make sense? To sum up:
Searches row 6 for headers with the same name that only differs by a dot
Merges these columns and also deletes the duplicate data for row 7 "Torrstoff".
My edit based on #TimWilliams code.
Const HDR_ROW As Long = 6
Dim c As Range, sht As Worksheet, f As Range
Dim lr As Long, r As Long, tmp, delCol As Boolean
Set ws2 = wb2.Worksheets(1)
Set c = ws2.Cells(HDR_ROW, ws2.Columns.Count).End(xlToLeft)
Do While c.Column > 2
delCol = False 'reset delete flag
'look for a matching column header
Set f = ws2.Rows(HDR_ROW).Find(Replace(c.Value, ".", ""), _
lookat:=xlWhole)
'found a column and it's not the same one we're working on...
If Not f Is Nothing And f.Column <> c.Column Then
Debug.Print c.Address(), f.Address()
lr = ws2.Cells(ws2.Rows.Count, c.Column).End(xlUp).Row
'move any non-blank values over (source data has lots of spaces?)
For r = HDR_ROW + 2 To lr
tmp = Trim(ws2.Cells(r, c.Column).Value)
If Len(tmp) > 0 Then
ws2.Cells(r, f.Column).Value = tmp
End If
Next r
delCol = True 'going to delete this column
End If
Set c = c.Offset(0, -1)
If delCol Then c.Offset(0, 1).EntireColumn.Delete
Loop
Sub Tester()
Const HDR_ROW As Long = 6
Dim c As Range, sht As Worksheet, f As Range
Dim lr As Long, r As Long, tmp, delCol As Boolean
Set sht = ActiveSheet
Set c = sht.Cells(HDR_ROW, Columns.Count).End(xlToLeft)
Do While c.Column > 2
delCol = False 'reset delete flag
If Instr(c.Value, ".") > 0 Then
'look for a matching column header
Set f = sht.Rows(HDR_ROW).Find(Replace(c.Value, ".", ""), _
lookat:=xlWhole)
'found a column and it's not the same one we're working on...
If Not f Is Nothing And f.Column <> c.Column Then
Debug.Print c.Address(), f.Address()
lr = sht.Cells(Rows.Count, c.Column).End(xlUp).Row
'move any non-blank values over (source data has lots of spaces?)
For r = HDR_ROW + 2 To lr
tmp = Trim(sht.Cells(r, c.Column).Value)
If Len(tmp) > 0 Then
sht.Cells(r, f.Column).Value = tmp
End If
Next r
delCol = True 'going to delete this column
End If 'header has a no-"." match
End If 'header has a "."
Set c = c.Offset(0, -1)
If delCol Then c.Offset(0, 1).EntireColumn.Delete
Loop
End Sub

Replace a string in Column C based on matching index in Column A

I would appreciate any help on this matter. I am trying to create an Excel 2010 macro in VBA that will read strings in one spreadsheet row by row, and then search another spreadsheet to see if the value exists in a column of strings.
If/When it finds a matching string in column A, I would like to compare the string in column C of the original spreadsheet with the string in Column C of the spreadsheet being searched. If both strings are the same, I would like to move on back to the column A search and continue.
If the strings are different I would like to overwrite the string in Column C of the spreadsheet being searched. I would also like to highlight this change on the searched spreadsheet.
If no matching string is found in column A of the search spreadsheet, then I want to copy the row of the original spreadsheet into the searched spreadsheet and highlight it.
Here's what I have so far, but I can't seem to get it to work properly:
Sub SearchRows()
Dim bottomA1 As Integer
bottomA1 = Sheets("Original Spreadsheet").Range("A" & Rows.Count).End(xlUp).Row
Dim bottomA2 As Integer
bottomA2 = Sheets("Searched Spreadsheet").Range("A" & Rows.Count).End(xlUp).Row
Dim rng1 As Range
Dim rng2 As Range
Dim x As Long
Dim y As Long
Dim foundColumnA As Range
Dim foundColumnC As Range
For Each rng1 In Sheets("Original Spreadsheet").Range("A2:A" & bottomA1)
With Sheets("Searched Spreadsheet").Range("A2:A" & bottomA2)
Set foundColumnA = .Find(what:=rng1, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
For Each rng2 In Sheets("Original Spreadsheet").Range("E2:E" & bottomA1)
With Sheets("Searched Spreadsheet").Range("E2:E" & bottomA2)
Set foundSize = .Find(what:=rng2, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=True)
If foundColumnC Is Nothing Then
bottomE2 = Sheets("Column C Changes").Range("E" & Rows.Count).End(xlUp).Row
y = bottomA2 + 1
rng2.EntireRow.Copy Sheets("Column C Changes").Cells(y, "A")
Sheets("Column C Changes").Cells (y, "A").EntireRow.Interior.ColorIndex = 4
End If
End With
Next rng2
If foundTag Is Nothing Then
bottomA2 = Sheets("Column A Changes").Range("A" & Rows.Count).End(xlUp).Row
x = bottomA2 + 1
rng1.EntireRow.Copy Sheets("Column A Changes").Cells(x, "A")
Sheets("Column A Changes").Cells(x, "A").EntireRow.Interior.ColorIndex = 3
End If
End With
Next rng1
End Sub
You actually have too much code, but they're not set up cleanly. Qualify a lot of things as much as possible so it's cleaner, and try to be consistent with your style. This way you can identify the error as much as possible.
Anyway, on to the code. The basic logic you want is as follows, based on the details above:
Check if a string in Sheet1!A is in Sheet2!A.
If found, compare Column C values.
If Column C values are different, set value of Sheet2 to that in Sheet1 and highlight.
Else, exit.
If not found, copy whole row to Sheet2 and highlight.
Now that we have that written down, it's simpler! :)
Please check my screenshots for my set-up:
SCREENSHOTS:
Sheet1:
Sheet2:
Note that for Sheet2, I don't have BK207 onwards. ;) Now, onto the code.
CODE:
Sub LoopMatchReplace()
Dim ShSrc As Worksheet, ShTar As Worksheet
Dim SrcLRow As Long, TarLRow As Long, NextEmptyRow As Long
Dim RefList As Range, TarList As Range, RefCell As Range, RefColC
Dim TarCell As Range, TarColC As Range
Dim IsFound As Boolean
Dim ToFind As String
With ThisWorkbook
Set ShSrc = .Sheets("Sheet1")
Set ShTar = .Sheets("Sheet2")
End With
'Get the last rows for each sheet.
SrcLRow = ShSrc.Range("A" & Rows.Count).End(xlUp).Row
TarLRow = ShTar.Range("A" & Rows.Count).End(xlUp).Row
'Set the lists to compare.
Set RefList = ShSrc.Range("A2:A" & SrcLRow)
Set TarList = ShTar.Range("A2:A" & TarLRow)
'Initialize boolean, just for kicks.
IsFound = False
'Speed up the process.
Application.ScreenUpdating = False
'Create the loop.
For Each RefCell In RefList
ToFind = RefCell.Value
'Look for the value in our target column.
On Error Resume Next
Set TarCell = TarList.Find(ToFind)
If Not TarCell Is Nothing Then IsFound = True
On Error GoTo 0
'If value exists in target column...
If IsFound Then
'Compare the Column C of both sheets.
Set TarColC = TarCell.Offset(0, 2)
Set RefColC = RefCell.Offset(0, 2)
'If they are different, set the value to match and highlight.
If TarColC.Value <> RefColC.Value Then
TarColC.Value = RefColC.Value
TarColC.Interior.ColorIndex = 4
End If
Else 'If value does not exist...
'Get next empty row, copy the whole row from source sheet, and highlight.
NextEmptyRow = ShTar.Range("A" & Rows.Count).End(xlUp).Row + 1
RefCell.EntireRow.Copy ShTar.Rows(NextEmptyRow)
ShTar.Rows(NextEmptyRow).SpecialCells(xlCellTypeConstants).Interior.ColorIndex = 3
End If
'Set boolean check to False.
IsFound = False
Next RefCell
Application.ScreenUpdating = True
End Sub
Kindly read the comments for the codeblocks so you get an understanding of what I'm doing. Also, note the way that I have qualified everything and properly set them up in a very clean way. Clean code is 50% good code.
Check the following screenshot to see the results after running the code.
END RESULT:
Note the added rows at the end and the changed values in Column C. I did not have the whole row highlighted as I believe that's bad practice and messy, but it's up to you to change the respective lines and values to suit your taste for the end result.
Let us know if this helps.
I think you can use this code.
Values not found will be added to the end of destination sheet.
Differences are signed with a blue(change if you want) background color.
Sub copy_d()
Dim r1 As Long, rfound, vfound
Dim w1, w2, v, lastR As Long, lastC As Long
Set w1 = Sheets("sheet1") ' change the origin sheet at will
Set w2 = Sheets("sheet2") ' change the destination sheet at will
r1 = 1 ' assuming data start in row 1, change it if not
Do While Not IsEmpty(w1.Cells(r1, 1))
v = w1.Cells(r1, 1)
rfound = Application.Match(v, w2.Columns(1), 0) ' look for value
If Not IsError(rfound) Then ' found it?
vfound = w2.Cells(rfound, 3)
If w1.Cells(r1, 3) <> vfound Then ' value in column C is different?
w2.Cells(rfound, 3) = w1.Cells(r1, 3) ' update based on origin sheet
lastC = w2.Cells(rfound, 1).End(xlToRight).Column
w2.Range(w2.Cells(rfound, 1), w2.Cells(rfound, lastC)).Interior.ColorIndex = 5
End If
Else
lastR = w2.Cells(1, 1).End(xlDown).Row + 1
w1.Rows(r1).copy Destination:=w2.Rows(lastR) ' copy to last row of dest sheet
lastC = w2.Cells(lastR, 1).End(xlToRight).Column
w2.Range(w2.Cells(lastR, 1), w2.Cells(lastR, lastC)).Interior.ColorIndex = 5
End If
r1 = r1 + 1
Loop
End Sub