vba find values in sheet2 to fit values in sheet1 - vba

I have two data ranges:
DataRange is the range in Sheet1 (something like A16:F30)
HoursDataRange is the range in Sheet2 (something like A17: G90).
I need to loop via DataRange rows, take values from row, do some manipluation (like adding those data into seeprate wrokbook), as well, as take corresponding cell in column A and find all rows in Sheet2 (HoursDataRange). I do not know how to do the last thing - find all matching rows in Sheet2.
I am not familiar with VBA yet, so I have read that I can use AutoFilters to filter HoursDataRange or lookups or loops.
What is the best solution?
As I am programmer, I do understand loops, but I am not so familar with VBA.
Here is a shortenedn example of Sheet1:
NAV Nr. CompName VAT Nr. Adress Name Type
101 Int1 1 Address1 Au 1
103 Int2 2 Address2 De 1
210 Int3 3 Address3 Es 1
212 Int4 4 Address4 Sw 1
310 Int5 5 Address5 Fi 1
345 Int6 6 Address6 Fr 1
And here is shortened example of Sheet2:
Key Acc Key NAV Nr. Client EUR
3 Bu STA BU 212 Cl1 25,00
4 Bc STA BC 101 Cl2 25,00
1 Bu STA BU 212 Cl1 25,00
2 Bc STA BC 101 Cl2 25,00
So, you see the column Nav Nr. is in both sheets and there are matching values. We can assume that each Nav Nr. occures only once in Sheet1 and I am already looping via Sheet1 DataRange. However, in Sheet2 given Nav Nr can appear from 0 to N times. So I need to find all matching rows (I need to find the whole row and not just cell, because I need manipulations for the all values in rows, for example, Later I would have to sum up EUR column by Nav Nr. and create PDF, but this woudl be later staff. FOr now I just want to know how to find those matching rows.

You'll just want to do exactly as you describe. Here's an example:
Sub renathy()
Dim Cdata As Range
Dim Chour As Range
For Each Cdata In Sheets("Sheet1").Range("A:A")
If Cdata <> "" Then
For Each Chour In Sheets("sheet2").Range("A:A")
If Cdata = Chour Then
'do stuff
End If
Next
End If
Next
End Sub

Related

How to create a named range of cells based on value of another column in excel vba

I have the following sheet of data
Channel Quarter Week value
a 1 1 5811
a 1 2 199
a 1 1 8111
a 2 2 881
a 2 1 124
b 2 2 1991
I need to update the value column based on the combination of Channel and Quarter columns (I have created a helper column which would serve as a key)
Helper Channel Quarter Week value
a1 a 1 1 5811
a1 a 1 2 199
a1 a 1 1 8111
a2 a 2 2 881
a2 a 2 1 124
b2 b 2 2 1991
From my VBA form, I have a created a dictionary with the names in these helper columns like
cellDict = [a1:= 1000, 2:= 2000, b1:= 500 etc]
Now I want to update the value of 'value' column on the basis of this dictionary in such a way that the cells corresponding to a1 be updated with 1000/3 each (As the number of rows for a1 is 3) and similarly cells corresponding to a2 be updated with 1000/2 each.
The attempt was to create a named range for value column with separate helper names and then iterate over each named range and update the cell value by taking the total value and dividing it by count of that named range
So, my question is how do I create a named range with value column on the basis of helper column so that I have (Assuming value is column V)
Range("a1") = V1:V3
Range("a2") = V4:V5 etc..
I think you can do this without named ranges in a lot easier way.
First of all, I assume the rows are sorted by your helper column!
Just find the first a1 in the helper column eg. with find method and get its row number as rowStart.
Then use WorksheetFunction.CountIf Method to count the occurrence of a1 in the helper column as rowCount. So rowEnd = rowStart + rowCount - 1.
Now you can loop like …
Dim iRow As Long
For iRow = rowStart to rowEnd
'use your dictionary and rowCount to replace values here.
'Example for accessing the cell:
Worksheets("MySheet").Cells(iRow, "E").Value = ""
Next iRow

Excel filter and regex match numbers to another worksheet

I'm a bit of an Excel noob so bear with me here. I have the following abridged sheet:
Sheet1
H AP AO
1 Transaction Description Employee Name Type
2 ER 12345678 blank blank
3 ER 13182984 blank blank
4 ER 18213289 blank blank
5 ER 13829429 blank blank
6 ER 89234024 blank blank
And another sheet in the same file to reference the names against:
Sheet2
E I
1 Expense Report Number Employee Name
2 12345678 Chris Rock
3 13182984 Hank Hill
4 18213289 Tom Sawyer
5 13829429 Elon Musk
6 89234024 Tupac Shakur
And I was wondering how to efficiently fill in the first excel sheet's Employee Name and Type columns from the matching report number of the second sheet as such:
Sheet1
H AP AO
1 Transaction Description Employee Name Type
2 ER 12345678 Chris Rock A
3 ER 13182984 Hank Hill A
4 ER 18213289 Tom Sawyer A
5 ER 13829429 Elon Musk A
6 ER 89234024 Tupac Shakur A
My attempt so far:
Set RE = CreateObject("vbscript.regexp")
RE.pattern = "(\d{8})"
Set allMatches = RE.Execute(ActiveSheet.Region ("H:H") #extract the 8 numbers
#somehow extract the 8 numbers to reference against the second sheet
With .Columns(AP)
.Resize(.Rows.Count - 1).Offset(1).SpecialCells(xlCellTypeVisible).Formula = "=IF(ISERROR(VLOOKUP(reference number,EEM BI + mapping!I:I,2,0)),""Check employee ID"",VLOOKUP(reference number,EEM BI + mapping!I:I,2,0))"
As you can see I'm pretty lost in this code.. Any help is much appreciated
try this test code
Sub Test()
Dim ddd As Variant ' convert sheet1.columnH into an array
ddd = Sheets("Sheet1").Range("h2:h6").Value ' 2D array 1 x N
ddd = Application.Transpose(ddd) ' 2D array N x 1
ddd = Application.Transpose(ddd) ' this changes to 1D array
Dim i As Integer
For i = 0 To UBound(ddd) ' remove the "ER" from each member of the array
ddd(i) = Split(ddd(i))(1)
Next i
Dim findMe As String
Dim rng As Range
For Each rng In Sheets("Sheet2").Range("e2:e6")
findMe = rng.Value
For i = 1 To UBound(ddd)
If StrComp(findMe, ddd(i), vbTextCompare) = 0 Then
Sheets("Sheet1").Range("ap1").Offset(i) = rng.Offset(0, 4).Value
Sheets("Sheet1").Range("ao1").Offset(i) = "A"
End If
Next i
Next rng
End Sub
In your table in Sheet1 if the 8 digit number always starts at position 4, as you show, you can use the MID function seen in the formula below. If not, we would merely have to change MID to something a bit more complex, depending on the real data. No need for REGEX unless the text analysis is complex.
Given the order of Employee Name and Expense Report Number in your lookup table, INDEX(MATCH(... would be one solution.
Although you could use LOOKUP, it may be more efficient to use INDEX(MATCH.... LOOKUP, among other things, to work properly, requires that your lookup table be sorted. That is not necessary with INDEX/MATCH.
Something like
=INDEX(EmployeeName,MATCH(--MID(H2,4,8),ExpenseReportNumber,0))
For efficiency, the references to the two columns (EmployeeName and ExpenseReportNumber) should be as short as possible. Whole column references (eg: $E:$E and $I:$I will work, but will take longer to execute.

Compare two sheets using ID column

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

Compare two sheets and find differences, copy to third sheet

I have been trying to compare two sheets. The sheets are versions, one made in August, the other in September. In Sheet1, column C I have a unique ID that could also be in sheet 2, but could also be not present. On the other hand, I could have NEW ID's in sheet 2, that are not present in Sheet1.
I am trying to:
Identify IDs not in "other" sheet, copy entire row to sheet3
Check if C-column value exists in other sheet, then it has to find
the differences in THOSE two rows, 12 columns out
Example, in sheet1:
ID Jan Feb Mar Apr May
14578596 125 125 125 0 10
22345697 10 10 10 10 20
12563654 150 150 75 75 75
85745896 890 890 890 890 790
and in sheet 2:
ID Jan Feb Mar Apr May
14578596 125 125 125 0 10
12563654 150 150 75 75 75
85745896 890 890 790 890 790
87544545 0 0 0 0 10
In sheet 3, it should copy over the newly added ID 87544545 and all the values in the following columns. It should copy over the ID's 22345697 entire row as well, as being non-existing in the other sheet is considered a difference.
For the others, that exist in both sheets, it should Take "Jan-Jan" and return the difference value. So it should lookup if "ID" exists in other sheet, if it does, compare the Jan-Feb-Mar with each other. Note that ID's are NOT in the same position in the sheets. With ID 85745896 it would return:
ID Jan Feb Mar Apr May
85745896 0 0 100 0 0
I have tried to look at topics such as
Compare data from 2 sheets and find mismatches
and
Check if two rows are the EXACT SAME in MS Excel but can't seem to make them work for my challenge here.
Sub compare()
For i = 1 To last_cell_mainSheet
For j = 1 To last_cell_sheet2
If Worksheets("main_sheet").Range("a" & i).Value = Worksheets("sheet2").Range("a" & j).Value
Then
Worksheets("main_sheet").Range("C" & i).Value = Worksheets("sheet2").Range("b" & j).Value
End If
Next j
Next i
End Sub
The easiest way to solve this is with excel formulas. (if you only want to do it once, or occasionally.) If you need to repeat if often (or have massive amounts of data) use VBA>
You will need to find out about VLOOKUP and IF and ISNA.
Essentially you can add a column to both sheets that looks up the ID in the other sheet and returns Y or N if it is found or not.
You formaula will be something like:
=IF(ISNA(VLOOKUP(MyIDCell,TheTableInTheOtherSheet, 1, false)),"N","Y")
TheTableInTheOtherSheet is a range starting with the ID column (and only neededing one column)
Do the Jan-Jan bit.
Again use a vlookup formula column on sheet1 to get the value of Jan from sheet2. The add a formula to compare them.
You formula will be something like:
=VLOOKUP(MyIDCell,TheTableInTheOtherSheet, 2, false)
TheTableInTheOtherSheet is a range starting with the ID column (and two columns wide)
2 get the second column value
Once you have the data you can sort or filter to reduce the list ot thsoe you need to copy to sheet 3 (best to sort). Then copy and paste them.

How to define name of a range with duplicate values in VBA?

I'd like to know how to define name for a range with duplicate values and have it automatically run through a the whole table. Please see the table below.
A B
1 CODE Display
2 100 000
3 100 000
4 100 010
5 100 020
6 100 030
7 100 100
8 110 000
9 110 010
10 110 020
11 110 030
12 110 100
13 110 101
14 110 200
15 110 204
16 110 208
17 110 209
Now, I know that I can use the method Names.Add to define. However, my problem is to be able to get the name range of the duplicate values in Column A as shown in the snippet.
I want to define name of Range B2:B7 as "t_100", for example. What I can think of is to get the address range from A2:A7, offset 1 column, then use the Names.Add method to refers to B2:B7. And since A2:A7 range contains only "100", it begs the question how to get the range of a continues duplicate values.
That's my initial thought.
Filtering on a known value and then referencing the .SpecialCells(xlCellTypeVisible would be a good method of gathering the cells with duplicate column A values together. Counting to see if any particular value was the first occurrence of that value as you walked down the column would ensure that you were not unnecessarily repeating actions.
Sub t_000_name_table()
Dim rw As Long, val As Variant
With ActiveSheet
With .Cells(1, 1).CurrentRegion
.AutoFilter
For rw = 2 To .Rows.Count
val = .Cells(rw, 1).Value
If Not CBool(Application.CountIf(.Cells(1, 1).Resize(rw - 1, 1), val)) Then
.AutoFilter field:=1, Criteria1:=val
With .Offset(1, 1).Resize(.Rows.Count - 1, 1)
.SpecialCells(xlCellTypeVisible).Name = Format(val, "\t\_000")
End With
.AutoFilter field:=1
End If
Next rw
.AutoFilter
End With
End With
End Sub
I've used a shorthand name declaration statement which replies heavily on the defaults. It should come in as workbook scope and absolute cell range addressing for the Refers to:. If you wish to alter the scope or other property, you can use the MSDN VBA reference for Name Object .Add.
This should work well for non-contiguous ranges as well.