Error in finding the matched ID - vba

I have two Sheets sheet1, sheet2
With sheet1 i have id which always starts with 4, I look for this ID in sheet2, and pul the corresponding names and copy back to sheet1.
The ID is always 8 Digit Long.
during this , I have an Special case, where an ID has some Special charachters and charachters. eg: 41017734_dr_bad ; the code Fails in this case. I doesnot recognise the first 8 and Fails to paste in the another sheet.
Could someone suggest how to overcome this?
I have an idea we could use whilcard and also strlen function. But struck how to use in code.
Sub match()
Dim sh1 As Worksheet, sh2 As Worksheet
Dim cell As Range, cell2 As Range, lstcl As Variant, lstcl2 As Variant, rgFnd As Variant
Dim n As Double, ID As String
Set sh1 = ThisWorkbook.Sheets("S")
Set sh2 = ThisWorkbook.Sheets("P")
ID = "4"
lstcl = sh1.Range("N10000").End(xlUp).Row
lstcl2 = sh2.Range("L10000").End(xlUp).Row
'comparing columns N and L in both sheets
For Each cell In sh2.Range("L5:L" & lstcl2)
For n = 5 To lstcl
If cell = sh1.Range("N" & n) Then
'the cell in column M next to the matching cell is equal to the 4xxxxxxx number
cell.Offset(0, 1) = sh1.Range("N" & n)
'the next cell in column N is equal to the A2C number in column A
cell.Offset(0, 2) = cell.Offset(0, -11)
End If
Next
Next
'test that each cell in the first sheet corresponds to the located results in the second sheet _
'and pastes back the A2C number, using the Range.Find function
For Each cell2 In sh1.Range("N5:N" & lstcl)
If Left(cell2, 1) = ID Then
Set rgFnd = sh2.Range("M5:M" & lstcl2).Find(cell2.Value)
If Not rgFnd Is Nothing Then
cell2.Offset(0, 1) = sh2.Range(rgFnd.Address).Offset(0, 1)
End If
End If
Next
End Sub

Try this
Sub match()
Dim sh1 As Worksheet, sh2 As Worksheet
Dim cell As Range, cell2 As Range, lstcl As Variant, lstcl2 As Variant, rgFnd As Variant
Dim n As Double, ID As String
Set sh1 = ThisWorkbook.sheets("S")
Set sh2 = ThisWorkbook.sheets("P")
ID = "4"
lstcl = sh1.Range("N10000").End(xlUp).Row
lstcl2 = sh2.Range("L10000").End(xlUp).Row
'comparing columns N and L in both sheets
For Each cell In sh2.Range("L5:L" & lstcl2)
For n = 5 To lstcl
a = Left(sh1.Range("N" & n), 8)
If cell = a Then
'the cell in column M next to the matching cell is equal to the 4xxxxxxx number
cell.Offset(0, 1) = a
'the next cell in column N is equal to the A2C number in column A
cell.Offset(0, 2) = cell.Offset(0, -11)
End If
Next
Next
'test that each cell in the first sheet corresponds to the located results in the second sheet _
'and pastes back the A2C number, using the Range.Find function
For Each cell2 In sh1.Range("N5:N" & lstcl)
If Left(cell2, 1) = ID Then
Set rgFnd = sh2.Range("M5:M" & lstcl2).Find(cell2.Value)
If Not rgFnd Is Nothing Then
cell2.Offset(0, 1) = sh2.Range(rgFnd.Address).Offset(0, 1)
End If
End If
Next
End Sub

Related

Return Row 1 of Column where match was found

On my workbook, a command button is looping through every cell in column A, D, G and J.
If the cell contains a blue border, it's searching for its match on another workbook.
If that match is found, it's placing the cell value from original workbook to the 2nd workbook, in the next column of where the match was found.
I have 2 if statements checking if the next column is empty, and if it is then put the value there, if not then find the next empty cell in that row and put there.
I'm trying to return the first row (A1, D1, G1, or J1) from the original workbook, into the adjacent column of the newly placed values on the 2nd workbook.
Example:
On Workbook 1, the name "John Doe" and "Jane Doe" have a blue border in Column A.
On Workbook 2, "John Doe" was found in Column A, Row 123 and "Jane Doe" was found in Column A, Row 250.
The macro places "John Doe" in Column B, Row 123 and "Jane Doe" in Column B, Row 250 (assuming that cell in B123 and B250 are empty).
From Workbook 1, I want to also place the cell value in A1 - Into Workbook 2: Column C, Row 123 and 250.
But I want to do this for Columns A D G J simultaneously (rr3dest in my below code is what I'm trying to set this value to, I know it's not set to anything right now).
Private Sub CommandButton3_Click()
Dim testWS As Worksheet
Dim testRange As Range, idCella As Range
Dim alastRow2 As Long, resultM As Integer
Dim rr2dest As Range, rr3dest As Range
Set testWS = Workbooks("Test.xlsx").Worksheets("October") 'set the 2nd workbook as testWS
Set testRange = testWS.Columns(1) 'searching only column A on testWS (2nd workbook)
alastRow2 = Worksheets("Reruns To Pull").Cells(Rows.Count, "A").End(xlUp).Row 'find last row in column A that has data on current workbook
dlastRow2 = Worksheets("Reruns To Pull").Cells(Rows.Count, "D").End(xlUp).Row
glastrow2 = Worksheets("Reruns To Pull").Cells(Rows.Count, "G").End(xlUp).Row
jlastrow2 = Worksheets("Reruns To Pull").Cells(Rows.Count, "J").End(xlUp).Row
For Each idCella In Worksheets("Reruns To Pull").Range("A1:A" & alastRow2 & ",D1:D" & dlastRow2 & ",G1:G" & glastrow2 & ",J1:J" & jlastrow2).Cells 'for each cell in Column A on current workbook (eventually I want to loop through Column A, D, G, J. All will be variable ranges)
If idCella.Borders.Color = RGB(0, 0, 192) Then 'On current workbook, if cells in Col A borders.color = blue then
If Not IsError(Application.Match(idCella.Value, testRange, 0)) Then 'find exact match on Test.xlsx (2nd workbook) and store in variable resultM
resultM = (Application.Match(idCella.Value, testRange, 0))
If IsEmpty(testWS.Range("A" & CStr(resultM)).Offset(0, 1)) Then ' if resultM.offset(0,1) is empty then set destination to .offset(0,1)
Set rr2dest = testWS.Range("A" & CStr(resultM)).Offset(0, 1)
rr2dest.Value = idCella.Value
rr2dest.Interior.Color = idCella.Interior.Color
rr2dest.Borders.Color = idCella.Borders.Color
rr2dest.Borders.Weight = idCella.Borders.Weight
Set rr3dest = testWS.Range("A" & CStr(resultM)).Offset(0, 2)
ElseIf Not IsEmpty(testWS.Range("A" & CStr(resultM)).Offset(0, 1)) Then ' if resultM.offset(0,1) is not empty then set destination to .end(xltoright).offset(0,1)
Set rr2dest = testWS.Range("A" & CStr(resultM)).End(xlToRight).Offset(0, 1)
rr2dest.Value = idCella.Value
rr2dest.Interior.Color = idCella.Interior.Color
rr2dest.Borders.Color = idCella.Borders.Color
rr2dest.Borders.Weight = idCella.Borders.Weight
End If
End If
End If
Next idCella
testWS.Range("A2:M80").WrapText = True
testWS.Columns("A:M").HorizontalAlignment = xlCenter
testWS.Columns("A:M").VerticalAlignment = xlVAlignCenter
End Sub
Compiled but not tested:
Private Sub CommandButton3_Click()
Dim testWS As Worksheet, pullWS As Worksheet
Dim testRange As Range, idCella As Range
Dim arrSourceCols, col, v, m, c As Range
Set testWS = Workbooks("Test.xlsx").Worksheets("October") 'set the 2nd workbook as testWS
Set testRange = testWS.Columns(1) 'searching only column A on testWS (2nd workbook)
Set pullWS = ThisWorkbook.Worksheets("Reruns To Pull")
arrSourceCols = Array("A", "D", "G", "J") 'columns to be scanned and matched
For Each col In arrSourceCols 'loop source columns
For Each idCella In pullWS.Range(pullWS.Cells(1, col), _
pullWS.Cells(Rows.Count, col).End(xlUp)).Cells
If idCella.Borders.Color = RGB(0, 0, 192) Then
v = idCella.Value 'value to look for
m = Application.Match(v, testRange, 0) 'match?
If Not IsError(m) Then
Set c = testWS.Cells(m, Columns.Count).End(xlToLeft).Offset(0, 1) 'get empty cell
c.Value = v 'put the matched value
CopyFormats idCella, c 'transfer formatting
c.Offset(0, 1).Value = pullWS.Cells(1, col).Value 'put the header from the column
End If 'matched
End If 'blue borders
Next idCella
Next col
testWS.Range("A2:M80").WrapText = True
testWS.Columns("A:M").HorizontalAlignment = xlCenter
testWS.Columns("A:M").VerticalAlignment = xlVAlignCenter
End Sub
Sub CopyFormats(cFrom As Range, cTo As Range)
With cTo
.Interior.Color = cFrom.Interior.Color
.Borders.Color = cFrom.Borders.Color
.Borders.Weight = cFrom.Borders.Weight
End With
End Sub

VBA. Replace a table cell content based on match from another table or delete entire row if match is not found

I am trying to make the following to work:
There are two tables in a separate worksheets. I want it to check each cell in worksheet2 column B and find a match from worksheet1 column A. If a match is found then replace the data in worksheet2 column B with a data from a matching row of worksheet1 column B.
If a match is not found from a worksheet1 column A then delete entire row in a worksheet2 column B.
Sub match_repl_del()
Dim r1 As Long, rfound, vfound
Dim w1, w2, v As Long
Set w1 = Sheets(3) ' data sheet
Set w2 = Sheets(2) ' target sheet
r1 = 2 'data starting from row 2
Do While Not IsEmpty(w1.Cells(r1, 1))
v = w1.Cells(r1, 1)
rfound = Application.Match(v, w2.Columns(2), 0) ' look for value
If Not IsError(rfound) Then ' found it?
vfound = w2.Cells(rfound, 2)
If w1.Cells(r1, 2) <> vfound Then ' if value does not match sheet1 column b
w2.Cells(rfound, 2) = w1.Cells(r1, 2) ' update based on origin sheet
lastC = w2.Cells(rfound, 1).End(xlToRight).Column
w2.Range(w2.Cells(rfound, 1), w2.Cells(rfound, lastC)).Interior.ColorIndex = 5
Else ' delete entire row on sheet2 if match is not found
w2.Rows(r1).EntireRow.Delete
End If
End If
r1 = r1 + 1
Loop
End Sub
Try this wat, it's work for me :
Option Explicit
Sub test()
' Active workbook
Dim wb As Workbook
Set wb = ThisWorkbook
Dim i As Long
Dim j As Long
'*******************************************
'Adapt this vars
'define your sheets
Dim ws_1 As Worksheet
Dim ws_2 As Worksheet
Set ws_1 = wb.Sheets("Sheet1") 'find a match in worksheet1 column A
Set ws_2 = wb.Sheets("sheet2") 'cell in worksheet2 column B
'definie the last Rows
Dim lastRow_ws1 As Long
Dim lastRow_ws2 As Long
lastRow_ws1 = ws_1.Range("A" & Rows.Count).End(xlUp).Row 'if you need, adjust column to find last row
lastRow_ws2 = ws_2.Range("B" & Rows.Count).End(xlUp).Row 'if you need, adjust column to find last row
'*******************************************
For i = lastRow_ws2 To 2 Step -1
For j = 1 To lastRow_ws1
Dim keySearch As String
Dim keyFind As String
keySearch = ws_2.Cells(i, 2).Value
keyFind = ws_1.Cells(j, 1).Value
If keySearch = keyFind Then
'MsgBox keySearch & " " & keyFind & " yes"
ws_2.Cells(i, 2).Value = ws_1.Cells(j, 2).Value
GoTo next_i
End If
Next j
ws_2.Rows(i).EntireRow.Delete
next_i:
Next i
End Sub

Extracting a particular information from a cell

I have a sheet, S and P. In Sheet S, I have few ID starting with D2E and few Id starting with 4 in Column N.
I am comparing the ID, containing 4, with sheet P in column L. If they match, then I am writing the ID of sheet P from column A in Column N.
I have few case below in the snapshot, which I am not able to extract. Could any one help me , how I can do that
In sheet S , I have an Id like 41035036_drw_000_draf , in sheet P I am able to find the corresponding D2E number and I got it printed, but I want this number to be printed in my sheet S of column P.
I believe that I need to modify the rng.find function. that I it looks for first 8 character. Could any one help, how I can do that
Below is my code
Sub drwmatch()
Dim sh1 As Worksheet, sh2 As Worksheet
Dim cell As Range, cell2 As Range, lstcl As Variant, lstcl2 As Variant, rgFnd As Variant
Dim n As Double, ID As String
Dim a As String
Dim b As Variant
Set sh1 = ThisWorkbook.Sheets("S")
Set sh2 = ThisWorkbook.Sheets("P")
' ID starts with number 4
ID = "4"
lstcl = sh1.Range("N10000").End(xlUp).Row
lstcl2 = sh2.Range("L10000").End(xlUp).Row
'comparing columns N and L in both sheets
For Each cell In sh2.Range("L5:L" & lstcl2)
For n = 5 To lstcl
a = Left(sh1.Range("N" & n), 8)
If cell = a Then
'the cell in column M next to the matching cell is equal to the 4xxxxxxx number
cell.Offset(0, 1) = a
'the next cell in column N is equal to the A2C number in column A
cell.Offset(0, 2) = cell.Offset(0, -11)
End If
Next
Next
'test that each cell in the first sheet corresponds to the located results in the second sheet _
'and pastes back the A2C number, using the Range.Find function
For Each cell2 In sh1.Range("N5:N" & n)
If Left(cell2, 1) = ID Then
Set rgFnd = sh2.Range("M5:M" & lstcl2).Find(cell2.Value)
If Not rgFnd Is Nothing Then
cell2.Offset(0, 1) = sh2.Range(rgFnd.Address).Offset(0, 1)
End If
End If
Next
End Sub
to have a search on the first 8 chars you could write your find instruction like this
Set rgFnd = sh2.Range("M5:M" & lstcl2).Find(Left(cell2.Value, 8), lookat:=xlPart)

Searching multiple cells in multiple worksheets and then copying another cells value in a summary sheet

I have a workbook that has 4 worksheets all of which have dates on row 5, stating at column D. In the cell next to the date the person will put either 'ET','LT','EG','1ET', '2LT' or they will leave it blank.
I am reading on how VBA works at the moment but I have just started so very new to this.
I have this so far:
Sub test()
Dim summarySheet As Worksheet
Dim sh As Worksheet
Dim j As Integer
'change "Summary" to the sheet name that is true for you'
Set summarySheet = ThisWorkbook.Worksheets("Summary")
'number of first row where need to paste in summary sheet'
j = 2
'loop throught all sheets'
For Each sh In ThisWorkbook.Worksheets
If sh.Name <> summarySheet.Name Then
summarySheet.Range("B" & j & ":AF" & j).Value = _
sh.Range("D5:AH5").Value
j = j + 1
End If
Next
End Sub
It displays all the sheets data, but what I need is if there is either ET or LT entered in row 5 next to the date then it adds the corresponding data from row 37 into a summary sheet. If it's just the number then it is to skip that and find the next ET or LT
EG
Sheet 1
Row 5 1ET 2LT 3ET 4 5 6 7ET 8ET
===========================
Row 37 16 32 2 45 67
Sheet 2
Row 5 1 2 3LT 4ET 5ET 6LT 7 8LT
===========================
Row 37 23 33 13 22 34
SUMMARY SHEET
ET LT
1 16
2 32
3 2 23
4 33
5 13
6
7 45
8 67 34
9
Etc
I don't completely understand what you are trying to do. Your code copies the range exactly to the Summary sheet, but it looks like the result you want transposes them - has the numbers/dates running down the rows instead of across the rows. Also, you say "dates" but have the numbers 1-9 on the Summary Sheet and have the numbers 1-9 on your Sheet1 and Sheet2. I also cannot tell which column the "corresponding" values in row 37 are.
Therefore, this code may not exactly work for you as it based on the assumptions that 1) you do NOT want D5:AH5 from each sheet pasted exactly onto the Summary sheet; 2) since they are the only ones you mention as criteria, "ET" and "LT" are the only codes next to "dates" you care about; 3) the value in row 37 is in the same column as the "date"; 4) the "1ET" and "2LT" in your data represent a "1" in D5, "ET" in E5, "2" in F5, "LT" in G5, and so on; 5) since you used the numbers 1-9, the row for pasting the value from row 37 is determined by taking the "date" and adding 1. If you have actual dates, you will need to change your logic for pasteRow.
Sub test()
Dim summarySheet As Worksheet
Dim sh As Worksheet
Dim searchRng As Range
Dim dateCell As Range
Dim pasteCol As Integer
Dim copyRow As Integer
Dim pasteRow as integer
'change "Summary" to the sheet name that is true for you'
Set summarySheet = ThisWorkbook.Worksheets("Summary")
'the "corresponding row" to copy
copyRow = 37
'loop throught all sheets'
For Each sh In ThisWorkbook.Worksheets
If sh.Name <> summarySheet.Name Then
'set the range that we are using
Set searchRng = sh.Range("D5:AH5")
For Each cell In searchRng
'loop through the range and check if it has the desired key value
If cell.Value = "ET" Or cell.Value = "LT" Then
'set which column on SummarySheet will get the value
If cell.Value = "ET" Then
'column B, ie column #2
pasteCol = 2
ElseIf cell.Value = "LT" Then
'column C, ie column #3
pasteCol = 3
End If
'set the cell containing the date - assumes is to the left of our key value cell
Set dateCell = cell.Offset(0, -1)
'set row # to paste to, ie if the value in dateCell is 9, then paste to row 10
pasteRow = dateCell.Value + 1
'set the value on summarySheet using the value in dateCell + 1 for our row number
'and dateCell's column with copyRow to get our "corresponding" value
summarySheet.Range(Cells(pasteRow, pasteCol).Address).Value = _
sh.Range(Cells(copyRow, dateCell.Column).Address)
End If
Next cell
End If
Next
End Sub
EDITED based on new information from actual spreadsheet:
Sub test()
Dim summarySheet As Worksheet
Dim sh As Worksheet
Dim searchRng As Range
Dim dateNum As Integer
Dim pasteCol As Integer
Dim copyRow As Integer
Dim pasteRow As Integer
Dim c As Range
Dim oldVal As Integer
'change "Summary" to the sheet name that is true for you'
Set summarySheet = ThisWorkbook.Worksheets("Summary")
'clear current value on summarySheet
summarySheet.Range("C3:D33").Value = ""
'loop throught all sheets'
For Each sh In ThisWorkbook.Worksheets
If sh.Name <> summarySheet.Name Then
'set the range that we are using
Set searchRng = sh.Range("D5:AH5")
'the "corresponding row" to copy
With sh.Range("C:C")
Set c = .Find("Number of staff")
If Not c Is Nothing Then
copyRow = c.Row
End If
End With
For Each cell In searchRng
'loop through the range and check if it has the desired key value
If cell.Value Like "*ET" Or cell.Value Like "*LT" Then
'set which column on SummarySheet will get the value
If cell.Value Like "*ET" Then
'column C, so column #3
pasteCol = 3
ElseIf cell.Value Like "*LT" Then
'column D, so column #4
pasteCol = 4
End If
'get the date from the cell
dateNum = Val(cell.Value)
If dateNum = 0 Then
MsgBox "Sheet " & sh.Name & " cell " & cell.Address & " is missing date. Please fill in and run again."
Exit Sub
End If
'set row # to paste to, ie if the value in dateCell is 9, then paste to row 11
pasteRow = dateNum + 2
'set the value on summarySheet using cell's column with copyRow to get our "corresponding" value
oldVal = summarySheet.Range(Cells(pasteRow, pasteCol).Address).Value
summarySheet.Range(Cells(pasteRow, pasteCol).Address).Value = _
sh.Range(Cells(copyRow, cell.Column).Address).Value + oldVal
End If
Next cell
End If
Next
MsgBox "Complete"
End Sub
Option Explicit
Private Sub Worksheet_Activate()
Dim r As Range, rng As Range, snRow As Range, x As Integer
ActiveSheet.Range("C4:AG5").ClearContents
For x = 1 To Sheets.Count
If Sheets(x).Name <> "Summary" Then
With Sheets(Sheets(x).Name)
With .Range("C:C")
Set snRow = .Find("Number of staff", LookIn:=xlValues, lookat:=xlWhole)
End With
Set rng = .Range("D5", "AH5")
For Each r In rng
If InStr(1, r.Value, "LT") > 0 Then
Sheets("Summary").Cells(5, r.Column - 1) = .Cells(snRow.Row, r.Column).Value
ElseIf InStr(1, r.Value, "ET") > 0 Then
Sheets("Summary").Cells(4, r.Column - 1) = .Cells(snRow.Row, r.Column).Value
End If
Next
End With
End If
Next
End Sub
This achieves everything I wanted with the summary sheet going across the page instead of vertically.

Loop - Match values in two columns in different worksheets, copy entire row to new worksheet if match

I'm new in VBA coding, and would really appreciate some help solving this problem.
I need to do as follows:
Compare every value in column G, Worksheet1, to the Unique values in column D, Worksheet2.
If a value matches, copy from that row values in column: C, G & I
Paste every match into Worksheet3
I've tried this so far:
Sub test()
Application.ScreenUpdating = False
Dim rng1 As Range, rng2 As Range, rngName As Range, i As Integer, j As Integer
For i = 1 To Sheets("Worksheet1").Range("G" & Rows.Count).End(xlUp).Row
Set rng1 = Sheets("Worksheet1").Range("G" & i)
For j = 1 To Sheets("Worksheet2").Range("D" & Rows.Count).End(xlUp).Row
Set rng2 = Sheets("Worksheet2").Range("D" & j)
Set rngName = Sheets("Worksheet1").Range("H" & j)
If rng1.Value = rng2.Value Then
rngName.Copy Destination:=Worksheets("Worksheet3").Range("B" & i)
End If
Set rng2 = Nothing
Next j
Set rng1 = Nothing
Next i
End Sub
But it doesn't work.
There is a problem with this statement:
Set rngName = Sheets("Worksheet1").Range("H" & j)
The variable j refers to a row in Worksheet2, but you use it on Worksheet1. Depending on what you intended here, you should either change the worksheet name or use the variable i instead of j.
Assuming it is the first, the code could also be written as:
Dim rng1 As Range, rng2 As Range
' Iterate over the used cells in the G column of Worksheet1
For Each rng1 In Sheets(1).UsedRange.Columns(8 - Sheets(1).UsedRange.Column).Cells
' Iterate over the used cells in the D column of Worksheet2
For Each rng2 In Sheets(2).UsedRange.Columns(5 - Sheets(2).UsedRange.Column).Cells
If rng1.Value = rng2.Value Then
' Copy value from the C column in Worksheet2 to the B column in Worksheet3
Sheets(3).Cells(rng2.Row, 2).Value = rng2.Offset(0, -1).Value
End If
Next
Next
Alternative to VBA code
Instead of using code, you could do this with formulas.
For instance in Worksheet3 you could put this formula in B1:
=INDEX(Worksheet2!$C:$C, MATCH(Worksheet1!$G1,Worksheet2!$D:$D, 0))
Here is an explanation of the two main parts of that formula:
MATCH(Worksheet1!$G1, Worksheet2!$D:$D, 0)
This part will take the value from Worksheet1!$G1, find it in Worksheet2!$D:$D (i.e. the complete D column) and return the row number where it was found. The last argument (0) makes sure that only exact matches count.
INDEX(Worksheet2!$C:$C, ...)
The row number returned by MATCH will be used to get a value from the C column of Worksheet2, at that same row.
You can change that $C:$C by $H:$H to get the value from the H column, etc.
Drag/copy the formula downwards to repeat it for other rows.
I would use the Cells property and a Do loop to loop through G on WS1. Try something like this:
Dim i as Integer, j as Integer
Dim c as Range
i = 2 'Will be used to loop through WS1, Column G
j = 1 'Will be used to find next empty row in WS3
Do Until Sheets(1).Cells(i, 7).Value = ""
Set c = Sheets(2).Range("D2")
Do Until c.value = Sheets(1).Cells(i, 7).Value Or c.value = ""
Set c = c.Offset(1, 0)
Loop
If c.value = Sheets(1).Cells(i, 7).Value Then
'Find first empty row in WS3
j = 1
Do Until Sheets(3).Cells(j, 1).Value = ""
j = j + 1
Loop
'Copy row
Sheets(3).Rows(j).value = Sheets(1).Rows(I).value
End if
i = i + 1
Loop
Set c = Nothing