How to match two sets of cells on two sheets using vba - vba

I am trying to match an ID cell from sheet 1 to and ID cell in sheet 2. If these match then I need to match a product cell from sheet 1 to a product cell in sheet two.
The ID cell in sheet 1 has multiples of the same ID in a column with different products in the next cell (column A = ID, column B = product).
In sheet 2 there is only one instance of each ID, however the product goes across the row. If the two criteria match, I need a 1 to be placed in the cell below the product.
This needs to be looped across the row and once the row finishes, move to the next ID in sheet 1. If the criteria do not match then the cell needs to be filled with a 0.
The trouble I am have is moving to the next ID. I have included the code and appreciate any help.
Public Sub test()
Dim ws As Worksheet, sh As Worksheet
Dim wsRws As Long, dataWsRws As Long, dataRng As Range, data_Rng As Range, data_cell As Range, datacell As Range
Dim shRws As Long, prodShRws As Long, resRng As Range, res_Rng As Range, results_cell As Range, product_cell As Range, shCols As Long
Set dataSht = Sheets("Device Import")
Set resSht = Sheets("Transform Pivot")
With dataSht
wsRws = .Cells(.Rows.Count, "A").End(xlUp).Row
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
dataWsRws = .Cells(.Rows.Count, "B").End(xlUp).Row
Set dataRng = .Range(.Cells(2, "A"), .Cells(wsRws, "A"))
Set data_Rng = .Range(.Cells(2, "B"), .Cells(wsRws, "B"))
End With
With resSht
shRws = .Cells(Rows.Count, "A").End(xlUp).Row
shCols = .Cells(1, Columns.Count).End(xlToLeft).Column
Set resRng = .Range(.Cells(2, "A"), .Cells(shRws, "A"))
Set res_Rng = .Range(.Cells(1, "B"), .Cells(1, shCols))
End With
i = 1
For Each data_cell In dataRng 'data sheet
For Each product_cell In res_Rng 'results sheet
For Each datacell In data_Rng 'data sheet
For Each results_cell In resRng 'results range
If data_cell = results_cell And datacell = product_cell Then
MsgBox data_cell.Value + " " + datacell.Value
results_cell.Offset(0, i) = 1 ' dcell = rcell so recell offset = 1
Else
MsgBox product_cell.Value + " " + results_cell.Value
results_cell.Offset(0, i) = 0 ' no match so rcell offset = 0
End If
If results_cell = "" Then
Exit For
End If
i = i + 1
Next results_cell ' Results ID column
i = 1
Exit For
Next datacell ' Data Product column cell
Next product_cell ' Results ID row
Next data_cell ' Data ID column cell
End Sub

An alternative approach would be
Initialize the resSht to 0's first
Loop only the dataSht looking at each ID Product pair
Use match to find the ID and product on resSht and fill in 1's as found
Public Sub Demo()
Dim dataSht As Worksheet, resSht As Worksheet
Dim rData As Range
Dim rwRes As Variant, clRes As Variant
Dim colResID As Long, rwResProd As Long
colResID = 1 '<-- Column in Result Sheet containing ID
rwResProd = 1 '<-- Row in Result Sheet containing Products
Set dataSht = Sheets("Device Import")
Set resSht = Sheets("Transform Pivot")
'Initialise to 0
With resSht
.Range(.Cells(rwResProd, .Columns.Count).End(xlToLeft).Offset(1, 0), _
.Cells(.Rows.Count, colResID).End(xlUp).Offset(0, 1)) = 0
End With
' Lookup each ID and Product pair from dataSht in resSht
With dataSht
For Each rData In .Range(.Cells(2, 1), .Cells(.Rows.Count, 1).End(xlUp))
rwRes = Application.Match(rData.Value2, resSht.Columns(colResID), 0)
If Not IsError(rwRes) Then
clRes = Application.Match(rData.Offset(0, 1).Value2, resSht.Rows(rwResProd), 0)
If Not IsError(clRes) Then
resSht.Cells(rwRes, clRes) = 1
Else
MsgBox "Product " & rData.Offset(0, 1).Value2 & " not found in Result Sheet", vbOKOnly + vbExclamation, "Missing Product"
End If
Else
MsgBox "ID " & rData.Value2 & " not found in Result Sheet", vbOKOnly + vbExclamation, "Missing ID"
End If
Next
End With
End Sub
Example Result

Related

Loop through row and headers on separate sheets in VBA

I have two sheets, sheet 1 has the data and sheet 2 has the headers. I am trying to fill sheet 2 row 2 with either a 1 or a 0 depending if the cell value in sheet 1 matches the header in sheet 2.
I have a range in sheet 1. I can loop through this range and fill in the first cell in sheet 2 row 2 with the correct information.
The next step is where I am struggling. I need to then move to the next header in sheet 2 but again loop through the range in sheet 1.
I tried nested for loops.
Sub LoopOne()
Dim sht As Worksheet
Dim NxtSht As Worksheet
Dim LastRow As Long
Dim LastCol As Long
Dim StartCell As Range
Dim StrtCell As Range
Dim ScndCell As Range
Set sht = Sheets("Sheet1")
Set NxtSht = Sheets("Sheet2")
Set StartCell = Range("A1")
Set StrtCell = NxtSht.Range("A1")
Set ScndCell = NxtSht.Range("A2")
sht.Activate
LastCol = sht.Cells(StartCell.Row, sht.Columns.Count).End(xlToLeft).Column
Range("A1").Select
sht.Range(StartCell, sht.Cells(LastCol)).Select
For Each cell In sht.Range(StartCell, sht.Cells(LastCol))
If cell.Value = Cells(StrtCell).Value Then
ScndCell.Value = 1
Else
If cell.Value <> Cells(StrtCell).Value Then GoTo escape
End If
escape:
NxtSht.Activate
Next cell
End Sub
Here is my quick stab at this using two nested for each x in y
Sub TestBed()
Dim myWB As Workbook, firstWS As Worksheet, secondWS As Worksheet, fHeaderRng As Range, sHeaderRng As Range, fOneCell As Range, sOneCell As Range
Dim fColUsed As Long, sColUsed As Long, debugStr As String
' Define Objects
Set myWB = ThisWorkbook
With myWB
Set firstWS = .Worksheets("Sheet1")
Set secondWS = .Worksheets("Sheet2")
End With
With firstWS
fColUsed = .UsedRange.Columns.Count
Set fHeaderRng = .Range(.Cells(1, 1), .Cells(1, fColUsed))
End With
With secondWS
sColUsed = .UsedRange.Columns.Count
Set sHeaderRng = .Range(.Cells(1, 1), .Cells(1, sColUsed))
End With
For Each sOneCell In sHeaderRng
For Each fOneCell In fHeaderRng
If fOneCell.Value = sOneCell.Value Then
debugStr = "Match || First Addr: " & fOneCell.Address & " || Second Addr: " & sOneCell.Address
Debug.Print debugStr
sOneCell.Offset(1, 0) = 1 ' 1 = Match
GoTo Next_sOneCell
Else
debugStr = "No Match || First Addr: " & fOneCell.Address & " || Second Addr: " & sOneCell.Address
Debug.Print debugStr
sOneCell.Offset(1, 0) = 0 ' 0 = No Match
End If
Next fOneCell
Next_sOneCell:
Next sOneCell
End Sub

How to find value of cell above each cell

I want to screen all sheets for values that starts with "D"
In the sheets I formed blocks (1 column, 4 rows) with
- owner
- area
- parcel (that is allways starting with a "D")
- year of transaction (blocks of 1 column and 4 rows).
I want to make a summary in sheet "Test".
I'm able to find the parcel, but how can I get the info from the cell above?
Sub Zoek_kavels()
Dim ws As Worksheet
Dim rng As Range
Dim Area
Dim Kavel As String
rij = 1
For Each ws In ActiveWorkbook.Sheets
Set rng = ws.UsedRange
For Each cell In rng
If Left(cell.Value, 1) = "D" Then 'Starts with D
Sheets("Test").Cells(rij, 1) = cell.Value 'Kavel D..
Cells(cell.row - 1, cell.Column).Select
Area = ActiveCell.Value
Sheets("Test").Cells(rij, 2) = Area 'Oppervlakte
Sheets("Test").Cells(rij, 3) = ws.Name 'Werkblad naam
rij = rij + 1
End If
Next
Next
End Sub
A nice simple loop should do the trick, you may have had spaces in the worksheet, that would throw off the used range.
Here is a different approach.
Sub Get_CellAboveD()
Dim LstRw As Long, sh As Worksheet, rng As Range, c As Range, ws As Worksheet, r As Long
Set ws = Sheets("Test")
For Each sh In Sheets
If sh.Name <> ws.Name Then
With sh
LstRw = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rng = .Range("A1:A" & LstRw)
If LstRw > 1 Then
For Each c In rng.Cells
If Left(c, 1) = "D" Then
r = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row + 1
ws.Range("A" & r).Value = c
ws.Range("B" & r).Value = c.Offset(-1).Value
ws.Range("C" & r).Value = sh.Name
End If
Next c
End If
End With
End If
Next sh
End Sub
There are two important points (and two not so important) to take care of your code:
start from row 2, because you are using .row - 1. Thus, if you start at row 1, row-1 would throw an error;
try to avoid Select, ActiveCell, etc.;(How to avoid using Select in Excel VBA);
write comments in English, not in Dutch (also good idea for variable names as well, rij or kavel do not help a lot);
declare the type of your variables, e.g. dim Area as String or as Long or anything else;
Option Explicit
Sub ZoekKavels()
Dim ws As Worksheet
Dim rng As Range
Dim Kavel As String
Dim rij As Long
Dim cell As Range
rij = 2 'start from the second row to avoid errors in .Row-1
For Each ws In ActiveWorkbook.Worksheets
Set rng = ws.UsedRange
For Each cell In rng
If Left(cell, 1) = "D" Then
With Worksheets("Test")
.Cells(rij, 1) = cell
.Cells(rij, 2) = ws.Cells(cell.Row - 1, cell.Column)
.Cells(rij, 3) = ws.Name
End With
rij = rij + 1
End If
Next
Next
End Sub
Or you can use .Cells(rij, 2) = cell.Offset(-1, 0) instead of Cells(cell.Row - 1, cell.Column), as proposed in the comments by #Shai Rado.

Match, Copy, and Add Values between Sheets

Looking to match values of column 1&2 of the same row on sheet2 to values of column 1&2 of the same row on sheet1. Then, copy entire row of sheet1 match onto next blank row of sheet3 + copy value of column 3+4 of same row sheet2 onto end of pasted row on sheet3.
IF Sheet2 Row First&Last (column1&2) Name match Sheet1 Row First&Last (column1&2)
THEN
Copy Sheet1 Row, paste to Sheet3 # next blank Row. Copy Sheet2 Row column 3+4 # end of previously pasted Row on Sheet3
Here is what I have so far, this doesn’t do anything right now but I have pieced it together from a few working macros to try and accomplish what I’m after. I haven’t been able to find examples of “Copy Sheet2 Row column 3+4 # end of previously pasted Row on Sheet3” so I just have a description on the line where I think the code should go.
Sub Match_Copy_AddValues()
Dim s1 As Worksheet, s2 As Worksheet, s3 As Worksheet
Application.ScreenUpdating = False
Application.EnableEvents = False
Set s1 = ActiveSheet 'List with dump data'
Set s2 = Sheets("Sheet 2") 'List of names to match, and additional information to be added'
Set s3 = Sheets("Sheet 3") 'Worksheet to copy rows of matched names'
Dim r As Long 'Current Row being matched?'
On Error GoTo fìn
Set ws2 = Sheets("Sheet 2")
With Sheets("Sheet 1")
r = Application.Max(.Cells(Rows.Count, 1).End(xlUp).Row, .Cells(Rows.Count, 2).End(xlUp).Row) 'Defines # of rows to apply If/Then to?'
For r = Application.Sum(v) To 2 Step -1 'Each time If/Then is ran, reduce # of rows to apply If/Then to?'
If CBool(Application.CountIfs(ws2.Columns(1), .Cells(r, 1).Value, ws2.Columns(2), .Cells(r, 2).Value)) Then _
.Rows(r).EntireRow.Copy s3.Cells(K, 1) 'Compares value in (r)row column 1 and 2, sheet2, to sheet1(activesheet), if equal THEN copies entire (r)row onto sheet3 # next empty row'
'take (r)row of match and copy value of column 3 and 4 sheet2 onto the end of previously pasted row on sheet3'
Next r
End With
fìn:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
The code below doesn't do everything just the way your attempt suggests but I wrote it in very plain language so that you will surely be able to teak it back into your track where it has transgressed to where it shouldn't go.
Sub MatchNameAndInfo()
' 02 Aug 2017
Dim WsInput As Worksheet
Dim WsInfo As Worksheet
Dim WsOutput As Worksheet
Dim Rl As Long ' Last row of WsInput
Dim R As Long ' WsInput/WsInfo row counter
Dim Tmp1 As String, Tmp2 As String ' Clm 1 and Clm2 Input values
Dim Cmp1 As String, Cmp2 As String ' Clm 1 and Clm2 Info values
Set WsInput = Worksheets("Krang (Input)")
Set WsInfo = Worksheets("Krang (Info)")
Set WsOutput = Worksheets("Krang (Output)")
Application.ScreenUpdating = False
With WsInput
Rl = Application.Max(.Cells(.Rows.Count, 1).End(xlUp).Row, _
.Cells(.Rows.Count, 2).End(xlUp).Row)
If Rl < 2 Then Exit Sub
For R = 2 To Rl ' define each input row in turn
Tmp1 = Trim(.Cells(R, 1).Value)
Tmp2 = Trim(.Cells(R, 2).Value)
Cmp1 = Trim(WsInfo.Cells(R, 1).Value)
Cmp2 = Trim(WsInfo.Cells(R, 2).Value)
If StrComp(Tmp1 & Tmp2, Cmp1 & Cmp2, vbTextCompare) = 0 Then
TransferData R, WsInfo, WsOutput
End If
Next R
End With
Application.ScreenUpdating = True
End Sub
Private Function TransferData(R As Long, _
WsInfo As Worksheet, _
WsOut As Worksheet)
' 02 Aug 2017
Dim Rng As Range
Dim Rt As Long ' target row
With WsInfo
Set Rng = .Range(.Cells(R, 1), .Cells(R, 4))
End With
With WsOut
Rt = Application.Max(.Cells(.Rows.Count, 1).End(xlUp).Row + 1, 2)
Rng.Copy Destination:=.Cells(Rt, 1)
End With
End Function

copy random row if condition meets

I have two columns one is user name and other one is decision now for each unique user i want 10% data.. for example if user name is Rohit and decision yes than 10% random of all rows where user decision was yes again for no 10% all the row of same user where decision is NO, This code is giving 10% data of unique name from column user only.
Sub Random10_EveryName()
Randomize 'Initialize Random number seed
Application.ScreenUpdating = False
'Copy Sheet1 to new sheet
Sheets("Sheet1").Copy After:=Sheets(Sheets.Count)
'Clear old data in Sheet 2
Sheets(2).Cells.ClearContents
'Determine Number of Rows in Sheet1 Column A
numRows = Sheets(Sheets.Count).Cells(Rows.Count, _
"A").End(xlUp).Row
'Sort new sheet by Column E
Sheets(Sheets.Count).Cells.Sort _
key1:=Sheets(Sheets.Count).Range("O1:D" & numRows), _
order1:=xlAscending, Header:=xlYes
'Initialize numNames & startRow variable
numNames = 1
startRow = 2
'Loop through sorted names, count number of current Name
For nameRows = startRow To numRows
If Sheets(Sheets.Count).Cells(nameRows, "D") = _
Sheets(Sheets.Count).Cells(nameRows + 1, "D") Then
numNames = numNames + 1
Else:
endRow = startRow + numNames - 1
'Generate Random row number within current Name Group
nxtRnd = Int((endRow - startRow + 1) * _
Rnd + startRow)
'Copy row to Sheet2, Delete copied Name
dstRow = Sheets(2).Cells(Rows.Count, "A").End(xlUp).Row + 1
Sheets(Sheets.Count).Rows(nxtRnd).EntireRow.Copy _
Destination:=Sheets(2).Cells(dstRow, 1)
Sheets(Sheets.Count).Cells(nxtRnd, "D").ClearContents
'Set Start Row for next Name Group, reset numNames variable
startRow = endRow + 1
numNames = 1
End If
Next
'Sort new sheet by Column O
Sheets(Sheets.Count).Cells.Sort _
key1:=Sheets(Sheets.Count).Range("O1:E" & numRows), _
order1:=xlAscending, Header:=xlYes
'Determine Number of Remaining Names in new sheet Column O
numNamesleft = Sheets(Sheets.Count).Cells(Rows.Count, _
"E").End(xlUp).Row - 1
'Determine 10% of total entries from Sheet1
percRows = _
WorksheetFunction.RoundUp((numRows - 1) * 0.2, 0)
'Determine how many extra rows are needed to reach 10% of total
unqNames = Sheets(2).Cells(Rows.Count, _
"E").End(xlUp).Row - 1
extRows = percRows - unqNames
'Warn user if number of Unique Names exceeds 10% of Total Entires
If extRows < 0 Then
MsgBox "Number of Unique Names Exceeds 10% of Total Entries"
'Delete new sheet
Application.DisplayAlerts = False
Sheets(Sheets.Count).Delete
Application.DisplayAlerts = True
Exit Sub
End If
'Extract Random entries from remaining names to reach 10%
'
'Allocate elements in Array
ReDim MyRows(extRows)
'Create Random numbers and fill array
For nxtRow = 1 To extRows
getNewRnd:
'Generate Random row numbers within current Name Group
nxtRnd = Int((numNamesleft - 2 + 1) * _
Rnd + 2)
'Loop through array, checking for Duplicates
For chkRnd = 1 To nxtRow
'Get new number if Duplicate is found
If MyRows(chkRnd) = nxtRnd Then GoTo getNewRnd
Next
'Add element if Random number is unique
MyRows(nxtRow) = nxtRnd
Next
'Loop through Array, copying rows to Sheet2
For copyrow = 1 To extRows
dstRow = Sheets(2).Cells(Rows.Count, "A").End(xlUp).Row + 1
Sheets(Sheets.Count).Rows(MyRows(copyrow)).EntireRow.Copy _
Destination:=Sheets(2).Cells(dstRow, 1)
Next
'Delete new sheet
Application.DisplayAlerts = False
Sheets(Sheets.Count).Delete
Application.DisplayAlerts = True
End Sub
you may try this (commented) code:
Option Explicit
Sub main()
Dim helpCol As Range, cell As Range
Dim resultSht As Worksheet
Set resultSht = GetOrCreateSheet("Results") '<--| change "Results" to your wanted name of the "output" sheet
With Worksheets("Decisions") '<--| change "Decisions" to your actual data sheet
With .Range("O1", .Cells(.Rows.Count, 1).End(xlUp)) '<--| reference data from in columns "A:O" from row 1 down to last not empty row of column "A"
Set helpCol = .Resize(, 1).Offset(, .Parent.UsedRange.Columns(.Parent.UsedRange.Columns.Count).Column) '<-- set a "helper" column where to paste "names" and get unique ones only
helpCol.Value = .Resize(, 1).Offset(, 3).Value '<--| paste "names" values from column "D" (i.e. offseted 3 columns from column "A") to "helper" column
helpCol.RemoveDuplicates Columns:=Array(1), Header:=xlYes '<-- get only unique "names" in "helper" column
For Each cell In helpCol.Offset(1).SpecialCells(xlCellTypeConstants) '<-- loop through unique "names" in "helper" column
.AutoFilter field:=4, Criteria1:=cell.Value '<-- filter reference data on 4th column (i.e. column "D") with current "name"
Filter2AndWriteRandom .Cells, 5, "YES", 0.1, resultSht '<-- filter again on 5th column (i.e. column "E") with "YES" and write random 10% in "output" sheet
Filter2AndWriteRandom .Cells, 5, "NO", 0.1, resultSht '<-- filter again on 5th column (i.e. column "E") with "NO" and write random 10% in "output" sheet
Next cell
End With
helpCol.ClearContents '<-- clear "helper" column
.AutoFilterMode = False '<-- show all rows back
End With
End Sub
Sub Filter2AndWriteRandom(rng As Range, fieldIndex As Long, criterium As String, perc As Double, resultSht As Worksheet)
Dim nCells As Long, nPerc As Long, iArea As Long, iRow As Long, iArr As Long
Dim sampleRows() As Long
Dim filteredRows() As Long
With rng '<-- reference passed range
.SpecialCells(xlCellTypeVisible).AutoFilter field:=fieldIndex, Criteria1:=criterium '<-- filter on its passed 'filterIndex' column with passed 'criterium'
nCells = Application.WorksheetFunction.Subtotal(103, .Resize(, 1)) - 1 '<-- count filtered cells, skipping header one
If nCells > 0 Then '<-- if any cell filtered other than header one
ReDim filteredRows(1 To nCells) '<-- resize the array that will collect the filtered rows row index
With .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible) '<-- reference filtered data only
For iArea = 1 To .Areas.Count '<-- loop through groups of cells into which data has been filtered down
For iRow = 1 To .Areas(iArea).Rows.Count '<-- loop through current 'Area' rows
iArr = iArr + 1 '<-- update filtered rows row index index
filteredRows(iArr) = .Areas(iArea).Rows(iRow).Row '<-- update filtered rows row index
Next iRow
Next iArea
End With
nPerc = WorksheetFunction.RoundUp(nCells * perc, 0) '<-- evaluate the number of rows to be randomly extracted
sampleRows = GetRandomSample(nCells, nPerc) '<-- get the array with randomly chosen rows index
For iRow = 1 To nPerc '<-- loop through number of rows to be randomly extracted
resultSht.Cells(resultSht.Rows.Count, 1).End(xlUp).Offset(1).Resize(, .Columns.Count).Value = .Rows(filteredRows(sampleRows(iRow))).Value '<-- update "output" sheet
Next iRow
End If
End With
End Sub
Function GetRandomSample(ByVal nNumbers As Long, nSamples As Long) As Long()
Dim numbers() As Long
Dim iSample As Long, i As Long
ReDim rndNumbers(1 To nSamples) As Long
numbers = GetNumbers(nNumbers)
For iSample = 1 To nSamples
i = Int((nNumbers * Rnd) + 1)
rndNumbers(iSample) = numbers(i)
numbers(i) = numbers(nNumbers)
nNumbers = nNumbers - 1
Next iSample
GetRandomSample = rndNumbers
End Function
Function GetNumbers(nNumbers As Long) As Long()
ReDim numbers(1 To nNumbers) As Long
Dim i As Long
For i = 1 To nNumbers
numbers(i) = i
Next i
GetNumbers = numbers
End Function
Function GetOrCreateSheet(shtName As String) As Worksheet
On Error Resume Next
Set GetOrCreateSheet = Worksheets(shtName)
If GetOrCreateSheet Is Nothing Then
Set GetOrCreateSheet = Worksheets.Add
ActiveSheet.Name = shtName
End If
End Function
user3598756 I HAVE DONE something HERE CAN YOU MAKE ANY CHANGE SO THAT IF VALUE= NO DEFECT THAN COPY ONLY 10% FROM the row which has same user and decision.
Sub test()
Dim lr As Long, lr2 As Long, R As Long, ws1 As Worksheet, ws2 As Worksheet, n As Long
Application.ScreenUpdating = False
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
Sheets(2).Cells.ClearContents
n = 1
lr = ws1.Cells(Rows.Count, "D").End(xlUp).Row
lr2 = ws2.Cells(Rows.Count, "E").End(xlUp).Row
For R = 2 To lr
If Range("D" & R).Value = "gadrooa" And Range("E" & R).Value = "NO_DEFECT" Then
Rows(R).Copy Destination:=ws2.Range("A" & n + 1)
n = ws2.Cells(Rows.Count, "A").End(xlUp).Row
End If
Next R
Application.ScreenUpdating = True
End Sub

Compare sheet 1 & 2 using column B1 as guide if not match copy row to sheet 3

I have an excel which has 3 sheets. In sheet 1 and 2 i have approximately 10 columns each but has different total number of rows. I want to check if data in Sheet 2 is in Sheet 1. If it has a match then do nothing but if it has no match then copy the entire row into sheet 3.
Here's my code But I think i got it wrong
Sub test()
Dim rng As Range, c As Range, cfind As Range
On Error Resume Next
Worksheets("sheet3").Cells.Clear
With Worksheets("sheet1")
Set rng = Range(.Range("A2"), .Range("a2").End(xlDown))
For Each c In rng
With Worksheets("sheet2")
Set cfind = .Columns("A:A").Cells.Find _
(what:=c.Value, lookat:=xlWhole)
If cfind Is Nothing Then GoTo line1
'c.EntireRow.Copy Worksheets("sheet3").Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
c.Copy Worksheets("sheet3").Cells(Rows.Count, "A").End(xlUp).Offset(1, 0)
c.Offset(0, 2).Copy Worksheets("sheet3").Cells(Rows.Count, "B").End(xlUp).Offset(1, 0)
End With 'sheet 2
line1:
Next c
Application.CutCopyMode = False
End With 'sheet 1
To explain it in picture refer below
Sheet 1
Sheet 2
Sheet 3
The Sheet 3 is my expected output. Can i obtain the output such as that.
Please help.
Thanks.
Try this one "
Sub test()
Dim rng As Range, c As Range, cfind As Range
On Error Resume Next
Worksheets(3).Cells.Clear
With Worksheets(1)
Set rng = .Range(.Range("A2"), .Range("a2").End(xlDown)) 'added . (dot) in front of first range
For Each c In rng
With Worksheets(2)
Set cfind = .Columns("A:A").Cells.Find _
(what:=c.Value, lookat:=xlWhole)
If cfind Is Nothing Then
'change the "10" in "Resize(1, 10)" to the number of columns you have
c.Resize(1, 10).Copy Worksheets(3).Cells(Worksheets(3).Rows.Count, "A").End(xlUp).Offset(1, 0)
End If
End With 'sheet 2
Next c
Application.CutCopyMode = False
End With 'sheet 1
End Sub
Edit for Avidan's question in comments
To check every row with every row on other sheet requires different approach. Such as :
Sub CopyMissingRecords()
'compare whole record in row on 1st worksheet with all records in rows on 2nd worksheet
'and if there is no such row in the 2nd worksheet, then copy the missing record to 3rd worksheet
'repeat for all records on 1st worksheet
Dim varToCopy() As Variant
Dim varToCompare() As Variant
Dim intCopyRow As Integer
Dim intCopyRowMax As Integer
Dim intToCompareRow As Integer
Dim intToCompareRowMax As Integer
Dim bytColumnsInData As Byte
Dim intMisMatchCounter As Integer
Dim intComparingLoop As Integer
Dim intRowMisMatch As Integer
bytColumnsInData = 10 ' change to your situation
'clear everything in our output columns in Worksheets(3)
With Worksheets(3)
.Range(.Cells(2, 1), .Cells(.Rows.Count, bytColumnsInData)).Clear
End With
With Worksheets(1)
'last row in Worksheets(1)
intCopyRowMax = .Cells(.Cells.Rows.Count, 1).End(xlUp).Row
'compare each row in Worksheets(1)
For intCopyRow = 2 To intCopyRowMax
'store the first row record from Worksheets(1) into memory
ReDim varToCopy(0)
varToCopy(0) = .Range(.Cells(intCopyRow, 1), .Cells(intCopyRow, bytColumnsInData))
With Worksheets(2)
'last row in Worksheets(2)
intToCompareRowMax = .Cells(.Cells.Rows.Count, 1).End(xlUp).Row
'loop through all rows in Worksheets(2)
For intToCompareRow = 2 To intToCompareRowMax
'store the actual row record from Worksheets(2) into memory
ReDim varToCompare(0)
varToCompare(0) = .Range(.Cells(intToCompareRow, 1), .Cells(intToCompareRow, bytColumnsInData))
'compare each column from the row record in Worksheets(1), with each column from the row record in Worksheets(2)
For intComparingLoop = 1 To bytColumnsInData
'if any of the cells from Worksheets(1) in compared row are different than cells from Worksheets(2) in compared row
'just one difference in row is enough to consider this record as missing
If varToCopy(0)(1, intComparingLoop) <> varToCompare(0)(1, intComparingLoop) Then
'store how many row MisMatches are there in data
intRowMisMatch = intRowMisMatch + 1
Exit For
End If
Next intComparingLoop
Next intToCompareRow 'next row in Worksheets(2)
'if there are as many row mismatches as there are row records in Worksheets(2)
If intRowMisMatch = intToCompareRowMax - 1 Then
With Worksheets(3)
'copy the entire row from Worksheets(1) to the next available row in Worksheets(3)
Worksheets(1).Range(Worksheets(1).Cells(intCopyRow, 1), Worksheets(1).Cells(intCopyRow, bytColumnsInData)).Copy _
Destination:=.Cells(.Cells.Rows.Count, 1).End(xlUp).Offset(1, 0)
End With 'Worksheets(3)
End If
'reset the counter
intRowMisMatch = 0
End With 'Worksheets(2)
Next intCopyRow 'next row in Worksheets(1)
End With 'Worksheets(1)
End Sub