I am looking to do a comparison of 2 sheets in a workbook in Excel 2013. Due to the number of records VLOOKUP and other formulas have been slow so I thought I would try VB to see if this was a quicker solution.
What I would like to do is compare each record by ID and highlight and mismatches in red. Due to the column names and position being different, I would also like to do the cell comparison on each record by specifying the column names to compare against. Finally, I would like to total the mismatches for each column into a 3rd sheet.
For example:
Sheet 1:
ID Col1 Col2 Col3 Col4
1 1 1 1 1
2 2 2 2 1
3 3 3 3 3
4 4 4 4 4
Sheet 2:
DBID Col1 Col2 Field Col3
1 1 1 1 1
2 2 2 2 2
4 4 4 4 4
3 3 3 3 3
So in the above example I would only like to Col4 compared with Field column and only see the Field column for ID 2 highlighted as an error with ID records 3 and 4 ignored because they match and are just in different positions in the file.
I would normally sort on ID instead of picking out a particular ID, but conscious that there could be records missing which means the data would be misaligned.
At the moment I have found this code which will highlight the mismatches in red, but matches cell by cell without taking into consideration that the columns and records might not be in the same order.
Sub RunCompare() 'Call the compareSheets routine Call compareSheets("Sheet1", "Sheet2") End Sub
Sub compareSheets(shtBefore As String, shtAfter As String) Dim mycell As Range Dim mydiffs As Integer 'If current cell is not a date then proceed (else skip and go to next), then 'if not same as corresponding cell in sheet After, 'mark as yellow and repeat until entire range is used For Each mycell In ActiveWorkbook.Worksheets(shtAfter).UsedRange If Not IsDate(mycell) Then
If Not mycell.Value = ActiveWorkbook.Worksheets(shtBefore).Cells(mycell.Row, mycell.Column).Value Then
mycell.Interior.Color = vbRed
mydiffs = mydiffs + 1
End If End If Next 'Display a message box stating the number of differences found MsgBox mydiffs & " differences found", vbInformation ActiveWorkbook.Sheets(shtAfter).Select End Sub
I am assuming that the ID is unique.
You have basically two solutions, with and without macro.
With Macro Logic can be as follows :
Get the first (Unique) column of first sheet
Loop through the first (Unique) column and find the matching row in second sheet
Compare between cells in that row with the first row of first sheet
Repeat the same steps for all rows
Also do a check to see if both sheets have same number of rows and columns; and no rows are duplicated.
Non Macro Solution :
Use VLookup Function to lookup for the row matching the value and do an equal comparison formula in a new sheet as
=IF(Sheet1!B1=VLOOKUP(Sheet1!A1,Sheet2!A:Z,2,FALSE),"Same","Different")
Note that you will need to increment the row number and column name I have highlighted in first column of the third (Answer) sheet.
Once you have values, you can use conditional formatting to highlight Different to Red
Related
So I have been given the task of comparing to worksheets in excel and if there is a match replacing the data from one cell with another, for example, I have 2 columns in 2 excel sheets, ID and name, I want to compare the IDs in sheet 1 with the IDs in sheet two and if it finds a match update the name linked with that ID.
Sheet 1
ID Name
1 Thomas
2 Jerry
Sheet 2
ID Name
3 Spike
1 Tom
So in the example above, I need the code to see that ID 1 is in both sheets and change the name in sheet 1 to match sheet 2, so that it looks like this:
ID Name
1 Tom
2 Jerry
I'm trying to use the Vlookup, which has allowed me to find out if it is existing or not, but then I don't know how to change the cell to match the existing one, here is my code so far:
Range("C2").Select
ActiveCell.Formula = _
"=IF(ISNA(VLOOKUP([#[ID]], 'Sheet2'!A:B,1,FALSE)), ""New"", ""Existing"")"
Do While Len(Range("A" & r).Formula) > 0
If (Range("C" & r).Value = "Existing") Then
Sheets("Sheet2").Range("A" & r & ":B" & r).Copy _
Destination:=Sheets("sheet1").Range("A" & r & ":B" & r)
Else
End If
I need to be able to get the cell number from the Vlookup so that I can use it in the if statement to pull in the correct data. There may be a simpler way to do this, if so I am open to changing everything.
Any help would be much appreciated.
I don't think there is a need of VBA for this task. As the names in "Sheet1" has to be updated by looking into the data in "Sheet2". Following formula can be used to find the updated names (by looking into data from the "Sheet2").
=IFERROR(VLOOKUP(A2,Sheet2!A2:B3,2,FALSE),B2)
IFERROR is used so as to retain the names which were not found in "Sheet2" data. Have a look at following screenshot for the example.
Easiest way is on a third sheet create 3 headings in row A: ID, Name and Source. Copy your data from sheet 1 into the first two columns and fill the third column with the text sheet 1. Do the same for sheet 2 but paste it below your sheet 1 data. You should end up with something like this:
ID Name Source
1 Thomas Sheet 1
2 Jerry Sheet 1
3 Spike Sheet 2
1 Tom Sheet 2
Then just create a pivot table from this data with source as the column, name as the row and a count of name for the data. It should look something like this:
Name Sheet 1 Sheet 2 Total
Thomas 1 0 1
Jerry 1 0 1
Spike 0 1 1
Tom 0 1 1
You can then sort on the Total column to find the duplicates which will have a total of two.
One other advantage of using this method is that it is quite easy to expand it to compare three or more lists.
I have three excel spreadsheets. The first has the values that are to be assigned to a new excel spreadsheet. The second has the column that the data belongs in. The third has the row that the data belongs in.
It looks something like this:
Data Value:
1 5 7 9
2 2 6 8
Column Number:
1 2 3 1
2 3 1 2
Row Number:
1 2 3 2
4 4 3 1
How can I combine all of this information to create a single spreadsheet that contains the values in a format like this:
Column
1 2 3
Row
1 1 8 0
2 9 5 0
3 6 0 7
4 0 2 2
I have tried to do it by using loops in vba, but I am a beginner and I am having some difficulty.
I know that I need to use a loop that checks the row and column that the data is supposed to be in against the row and column for each iteration. I am just not sure how to go about doing that.
Assuming these are different sheets in the same workbook (if not - create a new workbook and copy the sheets over). I assume that on each sheet, the same range of cells is used (for example A1:D2 in all 3 cases with the values on the first sheet, the column numbers in the second and the row numbers in the third). You can dispense with VBA entirely at the expense of using some complicate formulas (inspired by this excellent article: http://exceluser.com/blog/1043/how-to-create-two-dimensional-lookups-in-excel-formulas.html )
Step 1. Add a fourth sheet and in A1 add the formula
=CONCATENATE(Sheet3!A1,"_",Sheet2!A1)
and copy it over the appropriate range (e.g. A1:D2). This will give you things like 2_1 which tell you that the corresponding entry in sheet 1 belongs in row 2 column 1. Name this range "location" (formula tab - define names option)
Step 2 - Decide where you want to hold the data (I'm assuming it is in sheet 4 for simplicity) And add the row numbers (1-4) and the column numbers (1-3) as labels. In my case the row labels are in A5:A8 and the column labels in B4:C4 (see the screenshot below). Then in the upper left corner of the values to be filled in (B5 in my case) enter the following formula (suitably adjusted to match your ranges):
=IFERROR(INDIRECT(ADDRESS(SUMPRODUCT(ROW(location)*(location = CONCATENATE($A5, "_",B$4))),SUMPRODUCT(COLUMN(location)*(location = CONCATENATE($A5, "_",B$4))),,,"Sheet1")),0)
and copy it over the intended range. Be careful with the dollar signs - this formula mixes row absolute and column absolute references in an essential way. Somewhat oddly, it actually works:
I am trying to figure out if there are any differences between a list of data with another. In order for a row of data to "match" with another row, the row must have the same values in their corresponding column. The rows themselves do not have to be in any particular order. In particular, I am dealing with a parts list, where there are part numbers, descriptions, etc. I am trying to figure out if any rows of data are different from rows of data from another list.
I found Compare two sheets using arrays, which may have the answer to my problem, but I am having trouble figuring out how to adapt to my code due to inexperience in Visual Basic.
I was able to get it to work for a single column of data, comparing one column of data from one sheet to another, but cannot get it to compare entire rows of data.
Here is an example of I want this to work:
Sheet 1 Sheet 2
Column 1 Column 2 Column 1 Column 2
Row 1 22a 33 11 11
Row 2 22a 33a 22a 33
Row 3 55 22b 55 23b
The code in the link will tell you what is not in sheet 1 but in sheet 2 and vice versa. In this example, I would like the code to tell me Sheet 1 Row 2 and Sheet 1 Row 3 are not in Sheet 2, and Sheet 2 Row 1 and Sheet 2 Row 3 are not in Sheet 1 (Sheet 1 Row 1 and Sheet 2 Row 2 match).
If that is ok by you, you can do it without VBA using the following formula:
={IF(IFERROR(MATCH(A1&"|"&B1;Sheet7!$A$1:$A$3&"|"&Sheet7!$B$1:$B$3;0);-1)=-1;"Unique";"")}
Assuming that each of your tables start in A1 (so that the tables with three entries span A1:B3), and entering this formula into C1 (and copying it down), press CTRL+SHIFT+ENTER when entering the formula to create an array formula, this will show the word "Unique" in column C if the pair in that row on that sheet is not in any of the row-pairs on sheet 2.
You can then use conditional formatting to highlight unique rows, filter on the tables to include only unique rows, or some other way of doing what you need.
NOTE 1: I have entered my numbers in Sheet6 and Sheet7 instead of 1 and 2. The formula written above goes into Sheet6.
NOTE 2: My language use ; instead of , as function separator, so if yours use , you need to change that.
NOTE 3: You will need to expand the ranges Sheet7!$A$1:$A$3 and Sheet7!$B$1:$B$3 if your set grows (this will happen automatically if new rows are inserted in between the old ones). The best is still probably to create named ranges for each of the 4 columns, exchange the references with those, and manage the named ranges instead of the formulas.
NOTE 4: If your data set contains the character "|", you need to change that as well, to match some character that you for sure do not have there.
Alternatively you could in column C on each cheet enter (assuming first entry in C1)
=A1&"|"&B1"
and copy this down, then run the solution from your copied example using that C column instead of on A1 and B1.
I have a large datasheet, where each row has a column that gives it a unique identifier, like so:
Row Identifier Value
1 A 3
2 A 4
3 A 7
4 B 1
5 B 3
6 B 0
7 C 9
I want to be able to find the row number of the last duplicated identifier in a range. So, for example, if the identifier "B" was some unknown number of rows long, and I wanted to find the number of the last row that had the column identifier "B," how would I do so?
So far I've come up with code to select the row of the FIRST identifier:
' Select first row where first instance of <B> exists:
With ActiveWorkbook.ActiveSheet
Set First_B_Row = .Range("A:A").Find(What:="B", LookIn:=xlValues)
End With
Dim First_B_RowNumber As Long
First_B_RowNumber = First_B_Row.Row
ActiveWorkbook.ActiveSheet.Rows(First_B_RowNumber).Select
But, I want to be able to find the row number of the LAST identifier in a column full of them. Any ideas?
You are absolutely close. Instead of searching top to bottom, then search in reverse like this:
With ActiveWorkbook.ActiveSheet
Dim Last_B_RowNumber As Long
Last_B_RowNumber = .Range("A:A").Find(What:="B", After:=[A1], _
SearchDirection:=xlPrevious).Row
End With
Above code will find the last occurrence of B in Column A and assigns it's row number to a variable.
Your just missing the SearchDirection argument.
I’m struggling trying to develop an automated solution for the following challenge (ie apart from a button press, no user intervention):
I have a master ‘sheet that contains Accrual figures in monthly columns and an associated Receipt Number for this in a column immediately to the right. The Receipt columns have the month in the form: ‘Feb’, ‘Jun’, ‘Dec’ at the top.
I need to return a variety of cell data to another summary ‘sheet in the workbook from each row that matches the following criteria:
Identify the Receipt column based on a match of the month with an entered month in cell ‘x’ in the summary ‘sheet, eg if I type ‘Mar’, find the column headed ‘Mar’ in the master ’sheet.
Ignoring blank rows (ie there are data in Column A), if the cell in the first row of the Receipt column is blank, identify the row, select 6 different cells and return the contents to 6 specific cells in the first blank row (from a given row number) in the summary ‘sheet – then move onto the next row in the column and continue this process until the end (or a row limit). NB: the 'blank' cell will have a fill colour (conditionally formatted).
If the cell contains data, move to the next row down and continue the process.
A VBA routine I can attach to an onscreen button to update the results each time would do the job nicely. Although I've picked up bits of really useful code here, eg for checking each row for given conditions, I can’t get my head around a working solution to include returning the relevant cells to the summary 'sheet...
Any and all feedback greatly appreciated.
(Sorry - can't post images / screenshots yet...)
Update
Thanks for the quick response, and apols I couldn't append/paste-in a sample of the spreadsheet - apparently I need 10 points... :)
Slightly Different summary sheet (Sheet1). The columns are: Month (Col A), then 4 cells (TBD) to be returned to cols B-E, then Receipt No (Col F). The data come from each identified row in the master sheet (Sheet4) and are placed in the next available blank row in Sheet1. I can mod any examples given to match the actual positions.
I have the criteria for selecting the row (this is from a loop I've got working to identify the row, but using a fixed column reference [26 - Col Z] for a specific month):
If Not Cells(TheRow, 3).Value = "" And Cells(TheRow, 26).Value = "" And Cells(TheRow, 6).Value < Cells(TheRow, 25).Value Then... (do the other bit I'm stuck on)
Hope this is a bit clearer. Appreciate your help.
Can't add a comment, or chat (!) so further update:
Thanks Tony
The month column in the summary is to confirm the month reported on, as this will change when the user overwrites the source cell for the month they wish to parse the master sheet with. The person this data goes to will get these 7 columns and nothing else.
The mechanism has to find the Receipt col (month), then identify that row entry is blank AND col 3 on that row is not blank AND that the Accrual value [Rng.Column - 1] is greater than the PO value (Col 4) on that row. Once these criteria are established, the Receipt, Accrual, PO and 3 other data are selected, copied and pasted into the summary sheet on the next available blank row.
The master sheet has Accrual and Receipt for each month, so there is only one column to identify.
Hope this helps...
I am struggling to visualise you worksheets. I see the master sheet as something like:
... |Accrual| Jan|Accrual| Feb|Accrual| Mar|Accrual| Apr| ...
... | 1.23|A12 | | | 23.67|A14 | | |
... | | | 56.78|C34 | 178.12|C56 | | |
... | 2.34|B678 | | | | | 123.82|B821 |
... | | | | | 96.52|D56 | | |
Somewhere within the Summary sheet there is a list of months of interest.
I need a variable:
Dim MonOfInt As String
and a loop within which a month of interest will be loaded from the worksheet into this variable:
With Sheets("Summary")
MonOfInt = .Cells(R, C).Value
End With
The following is a possible skeleton for the code to move values for the month of interest:
Dim ColCrnt As Long
Dim Rng As Range
Dim RowCrnt As Long
Dim RowLast As Long
:
With Sheets("Master")
' Look for month of interest in row 1
Set Rng = .Rows(1).Find(MonOfInt)
End With
If Rng Is Nothing Then
' No columns for this month in Master
Else
' Accrual and Receipt columns for this month found
ColCrnt = Rng.Column - 1 ' Accrual column for month
' Find last used row in Accrual column
RowLast = .Cells(Rows.Count, ColCrnt).End(xlUp).Row
For RowCrnt = 2 To RowLast
' Code to extract values from Master and move to Summary here
Next
End If
End With
If you can add information to your question to confirm my visualisation and to give more information about (1) how to detect is a row is blank (other than testing the whole row which is an option) and (2) the source and destination of the six cells then I will try to pad out this answer.