How to compare a list of rows to another list of rows in Excel? - vba

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.

Related

How to lookup if my lookup data has duplicate values?

I am trying to lookup values from Table 1 to Table 2 based on Col1 in Table 1.
The catch is that Table 1 has duplicate values (for example, A is repeated 3 times) but I don't want to duplicate the returned value from Table 2.
How can this be done through either excel or sql (e.g. LEFT JOIN)?
What SQL are you using? Are you familiar with CTE and partition?
Have a look here: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/597b876e-eb00-4013-a613-97c377408668/rownumber-and-cte?forum=transactsql
and here: (answer and 2nd comment): Select the first instance of a record
You can use those ideas to create another field that tells you whether the row is the first, 2nd , 3rd etc occurrence of Col1. Eg you'd have something like
1 B Red 150
2 B Red 150
and you can then update col3 to be zero where this new field is not 1.
EDIT: since you asked about Excel: in Excel, sort by whatever criteria you may need (col 1 first, of course). Let's say that Col1 starts (excluding the heading) in cell C2. Set cell B2 =1. Then write this formula in cell B3:
=IF(C3=C2,B2+1,1)
and drag it all the way down. This will count the occurrences of col 1, ie it will tell you which is the first, 2nd etc time a given value appears in col1. You can then use it as as the basis to change the value in other columns.
Also, it is not good practice to have a column where the first cell has a different formula from the others. You can use the same formula nesting another IF and referencing the row, so as to set one formula for the first row and one for the others.

Compare Excel sheets values to update a third value

Example file So I have two sheets that each have lists of part numbers, plant where they come from and two columns on costs. What I need to do is scan them and if Sheet A and Sheet B both have a row with matching part numbers and the plant they come from, then A's two cost values are updated to match B's costs.
The next step is then to highlight all cells in Sheet A that are not on Sheet B and highlight all cells in Sheet B that were copied to Sheet A. I think this last part can be done at the same time the cell is being copied I'm just not sure how to do any of this.
This is a formula method.
Because you will not be changing all the values and I assume you want to keep those that do not have a match, then in an empty column next to the figures on sheet 1 put the following formula:
=IFERROR(INDEX(Sheet2!F$3:F$7,MATCH(1,INDEX((Sheet2!$D$3:$D$7=$A3)*(Sheet2!$B$3:$B$7=$C3),),0)),G3)
Then copy over one column and down the the end of the data.
The INDEX((Sheet2!$D$3:$D$7=$A3)*(Sheet2!$B$3:$B$7=$C3),) will create an array of 0 and 1's the same size as the data reference on sheet 2. In this instance it will create a 1 dimensional array that is 5 objects.
The position of these objects of 0 and 1 are relative to the rows. So for the first formula the return array will be {0,1,0,0,0} because only the second row of the data matches both the plant and the part number.
The MATCH(1,INDEX(...),0) then finds the first object in that array that is 1 and returns the relative position, in this case 2 as it is the second in the array.
The Outer INDEX(Sheet2!F$3:F$7,...) then returns the value in the range Sheet2!F$3:F$7 whose relative position is equal to the 2 passed from the MATCH(). So Sheet2!F4.
If no MATCH is found then the whole thing will throw a #N/A error so we capture that error with IFERROR(...,G3) and tell the formula to return the value in column G instead.
This will give you all the proper values:
Then you can copy and paste just the values back to the original spots and hide the columns with the formulas:
Sheet2 for reference:
If you want vba to do the last part of copy and past and hiding then use the macro recorder and then clean up the code.

Using VBA to create a grid from 3 spreadsheets with the row, column, and values

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:

vlookup if name is matched display employee id

Ive never used vlookups i have a spreedsheet not sure if this is the right function. I have two sheets
Sheet 1
first name last name username
Sheet 2
first name last name employee id business unit
I need in column D on sheet 1 to have employee id ive below. Pay no attention to column letters and sheets because i moved to another sheet to try getting this right.
=MATCH(B11,Sheet1!C:C,0)
Any help is much appreciated.
So you realize you have to match both first and last names? There are several ways to accomplish this depending on how many employees you have in sheet 2: a) small list could a two-column search using array formula; b) large list just create another column in both sheets joining last & first names and do a MATCH or VLOOKUP on them.
Since your needs are simple and to illustrate option (b):
Insert a column in both Sheet1 and Sheet2 after the "last name"; you should now have an empty column C in both sheets.
Assuming you have column headers in row one, and thus data starts in row two, set cell C2 in both sheets with function =B2&","&A2, then fill-down that formula on both sheets in all rows.
Set Sheet1 cell E2 to formula =VLOOKUP(Sheet1!C2, Sheet2!$C:$D, 2, False), and fill-down that formula in all rows.
Voila, employee IDs on Sheet1. I do have to say this is so Excel 101. There are all sorts of examples and tutorials on this easily found using even the most trivial Google searches.

VBA to check for blank cells in columns based on value in another column

Given
O 1 2 3 A
A 4 5 6 B
B 7 8 9 D
O 3
C 15
T 18
I'm looking for VBA code to validate that when column A contains a value that the remaining columns also contain values and when it doesn't contain a value, that columns 2 & 5 also contain values but 3 & 4 don't.
I've simplified the example, in a real sheet there will be many more columns and rows to check.
I've considered COUNTIF and INDEX/MATCH and array forumlas but from my understanding these all work on single columns at a time.
I want to do something like WHEN A1:An<>"" THEN COUNTBLANK(B:E) ELSE COUNTA (C:D)
Is the best way to use autofilter using blanks in A and then countblank and then a second autofilter for values in A.
Thanks
You can do it with a couple of nested IF formulae as follows:
=IF(A1<>"",
"A not empty, "&IF(COUNTBLANK(B1:E1)=0,
"B:E not blank",
"B:E have blanks"),
"A blank, "&IF(AND(COUNTBLANK(B1)+COUNTBLANK(E1)=0,
COUNTBLANK(C1)+COUNTBLANK(D1)=2),
"Columns 2&5 have values and Columns 3&4 don't",
"but condition not met"))
The reason for going down the VBA route is that I want a generic reusable function as opposed to a formula I copy between cells and sheets changing the columns etc along the way ending up with a lot of duplicate code.
So something that takes a column to test and a value to test it with. Third parameter would be a range of columns to validate, and the fourth parameter the validation.
I don't want any solution to have the columns hard coded and I don't want intermediate totals at the end of rows. This is fairly easily achieved in Excel itself...
The reason for trying to use countblank is that I can apply it to a range.
After a lot of searching I discovered this (the columns don't match the original example)
=SUMPRODUCT((A2:A19<>"")*(B2:D19=""))
=SUMPRODUCT((A2:A19="")*(D2:D19=""))
=SUMPRODUCT((A2:A19="")*(B2:C19<>""))
Nice huh? I just need to convert it into VBA now.
Thanks