Compare content of rows in two different sheets if content of the first cell is true - vba

What I am trying to do is coding a macro that compares the rows in sheet1 and sheet2 and highlights the differences. You can see the macro for that below.
My problem is that in case a row or more is added or deleted in the first sheet, all other rows shift up/down which results in a lot of cells being marked in the second sheet.
Since I have an identifier in column A I try to implement an extra line which first looks for the same identifier in sheet 1 and once found, compares the rows of sheet 1 and sheet two, which have the same identifier and then marks potential differences.
Since all my ideas have failed so far, or made the file very slow, I hope you can help me out.
Thank you very much!
Sub comparing()
Dim sh1 As Worksheet, sh2 As Worksheet
Dim rCount As Long, cCount As Long
Set sh1 = Worksheets(ActiveWorkbook.Worksheets.Count() - 1)
Set sh2 = Worksheets(ActiveWorkbook.Worksheets.Count)
rCount = sh1.Cells(Rows.Count, 1).End(xlUp).Row
cCount = sh1.Cells(1, Columns.Count).End(xlToLeft).Column
Dim r As Long, c As Integer
For r = 1 To rCount
For c = 1 To cCount
If sh1.Cells(r, c) <> sh2.Cells(r, c) Then
sh2.Cells(r, c).Interior.ColorIndex = 6
End If
Next c
Next r
Worksheets(Worksheets.Count).Select
End Sub

I haven't fully tested this, but you could use the worksheetfunction match inside your first for loop to find the corresponding Row in the second sheet:
Sub comparing()
Dim sh1 As Worksheet, sh2 As Worksheet
Dim rCount As Long, cCount As Long
Set sh1 = Worksheets(ActiveWorkbook.Worksheets.Count() - 1)
Set sh2 = Worksheets(ActiveWorkbook.Worksheets.Count)
rCount = sh1.Cells(Rows.Count, 1).End(xlUp).row
cCount = sh1.Cells(1, Columns.Count).End(xlToLeft).Column
Dim r As Long, c As Integer, sh2Row As Long
For r = 1 To rCount
'Find the matching row in Sheet2 by using the value in Column A from both sheets
sh2Row = Application.WorksheetFunction.Match(sh1.Cells(r, 1).Value, sh2.Range("A:A"))
For c = 1 To cCount
If sh1.Cells(r, c) <> sh2.Cells(sh2Row, c) Then
sh2.Cells(sh2Row, c).Interior.ColorIndex = 6
End If
Next c
Next r
Worksheets(Worksheets.Count).Select
End Sub

Related

How do I change this statically set range to a dynamic range? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have a summary sheet Consolidated Tracker and data sheets that won't be set statically as they'll be dates i.e Sheet1 renamed May 2018 Sheet2 renamed October 2018 Sheet3 renamed May 2019 etc.
The follow code checks for a match in Column B across two statically set worksheets Consolidated Tracker and May 2018.
If a match is found, it takes the value from cell C4 in May 2018 and sets C4 in the Consolidated Tracker to this value.
What I'd next like to achieve is to check:
Sheet3 and Set D4 in the Consolidated Tracker if a match is found.
Sheet4 and set E4 in the Consolidated Tracker if a match is found.
Sheet5 and set F4 in the Consolidated Tracker if a match is found.
I've got this far by myself but I'm unsure how to procede from here.
Thank you.
Option Explicit
Public Sub UpdateData()
Dim WsDest As Worksheet 'destination workbook to write in
Set WsDest = ThisWorkbook.Worksheets("Consolidated Tracker")
Dim WsSrc As Worksheet 'source workbook to match with
Set WsSrc = ThisWorkbook.Worksheets("May 2018")
Dim LastRow As Long 'last used row in workbook
LastRow = WsDest.Cells(WsDest.Rows.Count, "B").End(xlUp).Row
Dim iRow As Long, MatchedRow As Long
For iRow = 1 To LastRow 'loop through all rows from row 1 to last used row and update each row
MatchedRow = 0 'initialize
On Error Resume Next 'if no match found then ignore error
MatchedRow = WorksheetFunction.Match(WsDest.Cells(iRow, "B"), WsSrc.Columns("B"), 0) 'get the row number of the match
On Error GoTo 0 'reactivate error reporting
If MatchedRow > 0 Then 'if a match was found then copy values
WsDest.Cells(iRow, "C").Value = WsSrc.Cells(MatchedRow, "C").Value
End If
Next iRow
End Sub
Does this do what you want?
It uses the sheet index but I'm uneasy about that because sheets can easily be re-ordered and your code will blow up.
As it stands the code will run through from the first to penultimate sheet (assuming your destination sheet is last) so you might need to adjust the j loop.
Public Sub UpdateData()
Dim WsDest As Worksheet 'destination workbook to write in
Set WsDest = ThisWorkbook.Worksheets("Consolidated Tracker")
Dim LastRow As Long 'last used row in workbook
LastRow = WsDest.Cells(WsDest.Rows.Count, "B").End(xlUp).Row
Dim iRow As Long, MatchedRow As Variant, j As Long, c As Long
c = 3
For j = 1 To Sheets.Count - 1
For iRow = 1 To LastRow 'loop through all rows from row 1 to last used row and update each row
MatchedRow = Application.Match(WsDest.Cells(iRow, "B"), Worksheets(j).Columns("B"), 0) 'get the row number of the match
If IsNumeric(MatchedRow) Then 'if a match was found then copy values
WsDest.Cells(iRow, c).Value = Worksheets(j).Cells(MatchedRow, "C").Value
End If
Next iRow
c = c + 1
Next j
End Sub
Here is a better method which doesn't rely on sheet indexes.
Public Sub UpdateData()
Dim WsDest As Worksheet 'destination workbook to write in
Set WsDest = ThisWorkbook.Worksheets("Consolidated Tracker")
Dim LastRow As Long 'last used row in workbook
LastRow = WsDest.Cells(WsDest.Rows.Count, "B").End(xlUp).Row
Dim iRow As Long, MatchedRow As Variant, c As Long, ws As Long
c = 3
For Each ws In ThisWorkbook.Worksheets
If ws.Name <> WsDest.Name Then
For iRow = 1 To LastRow 'loop through all rows from row 1 to last used row and update each row
MatchedRow = Application.Match(WsDest.Cells(iRow, "B"), ws.Columns("B"), 0) 'get the row number of the match
If IsNumeric(MatchedRow) Then 'if a match was found then copy values
WsDest.Cells(iRow, c).Value = ws.Cells(MatchedRow, "C").Value
End If
Next iRow
c = c + 1
End If
Next ws
End Sub

Comparing two sheets and deleting the entire row

I have two sheets , Sheet1 and sheet2 .
Sheet 1 is my Source sheet and I am mentioning the item number in column A.
Sheet 2 is my destination sheet the contains the list of item number from the data base.
I am comparing the column A of source sheet with column E of my destination sheet, if they both have same item number then I am deleting the entire row.
I am using the below code for this. on 6 item number 4 are getting deleted and 2 are not getting deleted.
But, when I copy the same item number from the destination sheet to source sheet ,then it is getting deleted. I am not sure why this is happening. Could any one guide how I could figure this out.
below is the code
Sub spldel()
Dim srcLastRow As Long, destLastRow As Long
Dim srcWS As Worksheet, destWS As Worksheet
Dim i As Long, j As Long
Application.ScreenUpdating = False
Set srcWS = ThisWorkbook.Sheets("sheet1")
Set destWS = ThisWorkbook.Sheets("sheet2")
srcLastRow = srcWS.Cells(srcWS.Rows.count, "A").End(xlUp).Row
destLastRow = destWS.Cells(destWS.Rows.count, "E").End(xlUp).Row
For i = 5 To destLastRow - 1
For j = 1 To srcLastRow
' compare column E of both the sheets
If destWS.Cells(i, "E").Value = srcWS.Cells(j, "A").Value Then
destWS.Cells(i, "E").EntireRow.delete
End If
Next j
Next i
End Sub
Remember to loop in reverse order when you are trying to delete the rows otherwise rows may skipped from deletion even when they qualify the deletion criteria.
So the two For loops should be like this....
For i = destLastRow - 1 To 5 Step -1
For j = srcLastRow To 1 Step -1
Here is another approach:
Rather than looping through each item everytime in your source and destination sheets, just use MATCH function:
Function testThis()
Dim destWS As Worksheet: Set destWS = ThisWorkbook.Worksheets("Sheet8") ' Change to your source sheet
Dim srcWS As Worksheet: Set srcWS = ThisWorkbook.Worksheets("Sheet12") ' Change to your destination sheet
Dim iLR As Long: iLR = srcWS.Range("L" & srcWS.Rows.count).End(xlUp).Row ' Make sure you change the column to get the last row from
Dim iC As Long
Dim lRetVal As Long
On Error Resume Next
For iC = 1 To iLR
lRetVal = Application.WorksheetFunction.Match(srcWS.Range("L" & iC), destWS.Range("A:A"), 0)
If Err.Number = 0 Then
destWS.Range("A" & lRetVal).EntireRow.Delete
End If
Err.Clear
Next
On Error GoTo 0
End Function

VBA vlookup to copy specific columns from multiple sheets to master sheet

I am using Excel to produce reports for a billing system and I would like to use VBA to simplify the process of updating the excel. What I want to do is to use vlookup function to reflect columns (G:AI) from respective Named worksheets back to mastersheet. All sheets starts from row 4. (Row 3 is header)
So I'll further simplify the process as such:
VLOOKUP VBA (When changes made in the Named worksheets)
1. To enable Vlookup function in column (G:AI) in Mastersheet from Named worksheets ("John", "Charlie", "George")
2. As Mastersheet is a mixed data of John, Charlie and George, to input Vlookup formulas across column (G:AI) accordingly, then till last row of Mastersheet
3. My vlookup range will be from Named worksheets (John, Charlie, George), range (A1:AI) starting from column 7, row 4 till the end of the data.
ws1.Cells(r, c).Value = Application.VLookup(ws1.Cells(r, 1).Value, wsNames.Range("A1:AI500"), colnum, False)
Here are the codes I have so far. It's all I worked out (with help) as of now. Any help would be greatly appreciated.
My issue is, when running the code, vlookup values for ws11 is in the right place. However, vlookup values for ws12 and ws13 are shifted towards further left of the worksheet. For example,
while vlookup values for ws11 is in columns (A:AI) - the right columns
vlookup values for ws12 is in columns (AP:BR) - 7 columns from column AI and
vlookup values for ws13 is in columns (BY:DA) - 7 columns from column BR
Is there a line of code that I can insert to fix this?
Sub green_update()
Dim wb As Workbook, ws1 As Worksheet, ws11 As Worksheet, ws12 As Worksheet, ws13 As Worksheet
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("Sheet1")
Set ws11 = wb.Sheets("Sheet11")
Set ws12 = wb.Sheets("Sheet12")
Set ws13 = wb.Sheets("Sheet13")
Dim colNo As Long, ARowNo as Long
Dim for_col As Long, i As Long, r As Long, c As Long, colnum As Long
r = 4: c = 7: colnum = 7
Dim wsNames As Variant
For Each wsNames In Sheets(Array("sheet11", "sheet12", "sheet13"))
colNo = wsNames.Cells("4", Columns.Count).End(xlToLeft).Column
For for_col = 1 To colNo
ARowNo = wsNames.Cells(Rows.Count, "A").End(xlUp).row
For i = 1 To ARowNo
ws1.Cells(r, c).Value = Application.VLookup(ws1.Cells(r, 1).Value, wsNames.Range("A1:AI500"), colnum, False)
If IsError(ws1.Cells(r, c).Value) Then
ws1.Cells(r, c).Value = 0
End If
r = r + 1
Next
r = 4
colnum = colnum + 1
c = c + 1
Next
colnum = 7
Next wsNames
End Sub
I honestly can't see what can be causing the problem you describe based on the code posted. There is nothing substantially different in the code below - I have tidied up a couple of the loops and incorporated the last row variable. Let me know how you get on.
Sub green_update()
Dim wb As Workbook, ws1 As Worksheet
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("Sheet1")
Dim colNo As Long, ARowNo As Long
Dim for_col As Long, i As Long, r As Long, c As Long, colnum As Long
r = 4: c = 7: colnum = 7
Dim wsNames As Variant
For Each wsNames In Sheets(Array("sheet11", "sheet12", "sheet13"))
colNo = wsNames.Cells("4", Columns.Count).End(xlToLeft).Column
ARowNo = wsNames.Cells(Rows.Count, "A").End(xlUp).Row
For for_col = 1 To colNo
For i = 1 To ARowNo
ws1.Cells(r, c).Value = Application.VLookup(ws1.Cells(r, 1).Value, wsNames.Range("A1:AI" & ARowNo), colnum, False)
If IsError(ws1.Cells(r, c).Value) Then
ws1.Cells(r, c).Value = 0
End If
r = r + 1
Next i
r = 4
colnum = colnum + 1
c = c + 1
Next for_col
colnum = 7
Next wsNames
End Sub

How to copy a range of cells to another column in VBA?

Working Environment: Excel 2013
Target: Copy C1:C9 to B11:B19. D1:D9 to B21:B29. E1:E9 to B31:B39.....
After copying all the range to column B, copy A1:A9 to A11:A19(A21:A29....)
My idea is that:
1. select a range by using something like
range.end()
because in some of my sheets, there are only 4 test steps. so I need a syntax which can self inspect the used cells in a column.
do a range copy to column B.
leave 1 row in between considering about the page layout.
My piece of code is:
Worksheets("Master").Columns(3).UsedRange.Copy
Worksheets("Master").Range("B11").PasteSpecial
but seems like the Columns(i).UsedRange.Copy doesn't work. the pastespecial works.
My question is:
How to select the used range in columns? The number of columns are not fixed which means some of the sheets have 40 columns, but some of the other have maybe 30.
Thanks!
I attached one screenshot of the sheet for your reference.
Assuming you do not have more data in the columns to be copied, this should work
Sub copyToOneColumn()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Master")
Dim startCol As Integer
startCol = 3
Dim endCol As Integer
endCol = 10
Dim startRange As Range
Dim ra As Range
For i = startCol To endCol
Set startRange = ws.Range("A1").Offset(0, i - 1)
Set ra = ws.Range(startRange, ws.Cells(Rows.Count, startRange.Column).End(xlUp))
ra.Copy Destination:=ws.Range("B" & Rows.Count).End(xlUp).Offset(2, 0)
Next i
End Sub
You can do a copy (not technically a copy as it doesn't use the clipboard) directly like so:
Range("B1").Resize(Range("A1:A" & range("A" & Rows.Count).End(xlUp).Row).Rows.Count,1) = Range("A1:A" & range("A" & Rows.Count).End(xlUp).Row).Value
Effectively you are looking at B1 then resizing that to a range to be the number of columns in column A that are used with this: Range("A1:A" & range("A" & Rows.Count).End(xlUp).Row).Rows.Count
Then you are making this new range in column B = to the values of the same range in column A.
Note, this can be shortened if you are always starting at row 1 but the code I have given you will suffice if you start at a different row.
You may try something like this...
Sub CopyData()
Dim wsMaster As Worksheet
Dim lr As Long, lc As Long, r As Long, c As Long
Application.ScreenUpdating = False
Set wsMaster = Sheets("Master")
lr = wsMaster.Cells(Rows.Count, 1).End(xlUp).Row
lc = wsMaster.Cells(1, Columns.Count).End(xlToLeft).Column
r = lr + 2
If lr <= 9 Then
For c = 3 To lc
wsMaster.Range(wsMaster.Cells(1, c), wsMaster.Cells(lr, c)).Copy wsMaster.Range("B" & r)
wsMaster.Range("A1:A" & lr).Copy wsMaster.Range("A" & r)
r = wsMaster.Cells(Rows.Count, 2).End(xlUp).Row + 2
Next c
End If
Application.ScreenUpdating = True
End Sub

Multiple Rows and Columns to Single Column Excel

I have different data on multiple rows and columns in Excel and I want all the data to be on a single Column. I tried the Transpose Function but it's not helping me to get what I want.
This is what I have right now:
And this is what I want to get:
Can anyone kindly tell me how I can achieve that? Any built in function or Macro will be helpful. Thanks.
Try this code:
Sub RangetoColumn()
Dim LastRow As Long, LastColumn As Long
Dim CurrentSheet As Worksheet, TargetSheet As Worksheet
Dim i As Long, j As Long, Count As Long
Set CurrentSheet = ThisWorkbook.Worksheets("Sheet1")'-->change Sheet1 to your source sheet
Set TargetSheet = ThisWorkbook.Worksheets("Sheet2")'-->change Sheet2 to your target sheet
LastRow = CurrentSheet.Cells(Rows.Count, "A").End(xlUp).Row
Count = 1
For i = 1 To LastRow
LastColumn = CurrentSheet.Cells(i, Columns.Count).End(xlToLeft).Column
For j = 1 To LastColumn
TargetSheet.Range("A" & Count).Value = CurrentSheet.Cells(i, j).Value
Count = Count + 1
Next j
Next i
End Sub
Code will read Range from Sheet1 and will create a Column in Sheet2.
I think this tutorial should help you : tutorial
you can try that solution for your needs.
Try using & in both cells. Try like this A1&B1 to combine the data in cell A1 and cell B1; copy and paste, then enjoy.
this will have all current sheet cells listed down its column A and cleared all other adjacent columns
Option Explicit
Sub RangeToOneColumn()
Dim lastRow As Long, i As Long, j As Long
Dim rng As Range
Dim myArr As Variant
With ThisWorkbook.Worksheets("Sheet1") '<== change it to your needs
lastRow = .Cells(.rows.Count, "A").End(xlUp).Row
ReDim myArr(0 To lastRow - 1)
For i = 1 To lastRow
Set rng = .Range(.Cells(i, 1), .Cells(i, .Columns.Count).End(xlToLeft))
myArr(i - 1) = Application.Transpose(Application.Transpose(rng))
Next i
.Cells(1, 1).CurrentRegion.ClearContents
j = 1
For i = LBound(myArr) To UBound(myArr)
.Cells(j, 1).Resize(UBound(myArr(i))) = Application.Transpose(myArr(i))
j = j + UBound(myArr(i))
Next i
End With
End Sub
since it uses array, it runs faster than iterating a coping&pasting through cells