VBA remove matching first & last names across 2 worksheets - string

I need help modifying this code to match First and Last names across 2 worksheets, then remove matches from the Sub sheet. At the moment it only matches 2 columns across 1 sheet. Specifics:
How do i change this code so Names on 'Sheet 1' Column 'B' are Matched to names on 'sheet 2' column 'E' & all matches are deleted from 'Sheet 1". Same is repeated for 'Sheet 1' Column 'C' to 'Sheet 2' Column 'F'.
Sub CompareNames()
Dim rngDel As Range
Dim rngFound As Range
Dim varWord As Variant
Dim strFirst As String
With Sheets("ADULT Sign On Sheet")
For Each varWord In Application.Transpose(.Range("A1", .Cells(.Rows.Count,"A").End(xlUp)).Value)
If Len(varWord) > 0 Then
Set rngFound = .Columns("B").Find(varWord, .Cells(.Rows.Count, "B"), xlValues, xlPart)
If Not rngFound Is Nothing Then
strFirst = rngFound.Address
Do
If Not rngDel Is Nothing Then Set rngDel = Union(rngDel, rngFound) Else Set rngDel = rngFound
Set rngFound = .Columns("B").Find(varWord, rngFound, xlValues, xlPart)
Loop While rngFound.Address <> strFirst
End If
End If
Next varWord
End With
If Not rngDel Is Nothing Then rngDel.Delete
Set rngDel = Nothing
Set rngFound = Nothing
End Sub

Loops through all values in Sheet1 Column B. If that value is found in Sheet2 Column E, the entire row in Sheet1 is deleted. Then it loops through all values in Sheet1 Column C. If that value is found in Sheet2 Column F, the entire row in Sheet1 is deleted.
Sub DeleteCopy()
Dim LastRow As Long
Dim CurRow As Long
Dim DestLast As Long
LastRow = Sheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
DestLast = Sheets("Sheet2").Range("E" & Rows.Count).End(xlUp).Row
For CurRow = 2 To LastRow 'Assumes your first row of data is in row 2
If Not Sheets("Sheet2").Range("E2:E" & DestLast).Find(Sheets("Sheet1").Range("B" & CurRow).Value, LookIn:=xlValues, LookAt:=xlWhole) Is Nothing Then
Sheets("Sheet1").Range("B" & CurRow).Value = ""
Else
End If
Next CurRow
LastRow = Sheets("Sheet1").Range("C" & Rows.Count).End(xlUp).Row
DestLast = Sheets("Sheet2").Range("F" & Rows.Count).End(xlUp).Row
For CurRow = 2 To LastRow 'Assumes your first row of data is in row 2
If Not Sheets("Sheet2").Range("F2:F" & DestLast).Find(Sheets("Sheet1").Range("C" & CurRow).Value, LookIn:=xlValues, LookAt:=xlWhole) Is Nothing Then
Sheets("Sheet1").Range("C" & CurRow).Value = ""
Else
End If
Next CurRow
End Sub

Try this, you will have to call it twice once with the first criteria and then again with the second critiera
I think I have it set up properly for the first criteria
Sub DeleteIfMatchFound()
Dim SearchValues As Variant
Dim wsSource As Worksheet, wsTarget As Worksheet
Dim sLR As Long, tLR As Long, i As Long
Set wsSource = ThisWorkbook.Worksheets("Sheet1")
Set wsTarget = ThisWorkbook.Worksheets("Sheet2")
sLR = wsSource.Range("B" & wsSource.Rows.Count).End(xlUp).Row
tLR = wsTarget.Range("E" & wsSource.Rows.Count).End(xlUp).Row
SearchValues = wsSource.Range("B2:B" & sLR).Value
For i = 1 To (tLR - 1)
If Not IsError(Application.match(SearchValues(i, 1), wsTarget.Range("E2:E" & tLR), 0)) Then
wsTarget.Rows(i + 1).Delete
End If
Next i
End Sub

Related

Find all duplicates in a column of a certain value and return values from the next column

I am trying to make something that would look like this:
In the table on the right there will be all the unique records which will be stored in a certain area. However some record may be existing in more areas, and this information can be taken from the list in column A and B. The macro should take each unique record in column D and search for it in Column A, every time it finds it, should copy the location/area in column B and pasted next to the unique record in the table. I think I could do this with a loop, but what I created in the code below does not really works.
The second challenge is to make it understand that in a location has been copy into the table, the new found location needs to be pasted in the next free cell of that same unique record.
I am aware my code is a little scare but I would appreciate even just advice on which direction I should be looking... Thanks in advance!
Sub searcharea()
Dim UC As Variant, UCrng As Range, ra As Range
Set UCrng = Range("F2:F6")
For Each UC In UCrng
Set ra = Cells.Find(What:=UC, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ra.Offset(0, 1).Copy Destination:=Range("E2")
Next
End Sub
I would suggest looping through all Rows (Columns A + B), e.g.:
For i = 1 to Rows.Count
'DoStuff
Next i
For each row, you copy the value of A into D, if it is not there already.
You can access the values like this:
Cells(i, "A").Value
Cells(i, "B").Value
For finding values in a column, see here. If you found a duplicate, use another loop to check which column (E, F, G,..) in your specific row is the first empty one, and past the value of column B there.
Take a try:
Option Explicit
Sub test()
Dim LastRowA As Long, LastRowD As Long, i As Long, rngColumn As Long
Dim rng As Range
With ThisWorkbook.Worksheets("Sheet1")
LastRowD = .Cells(.Rows.Count, "D").End(xlUp).Row
.Range("D2:J" & LastRowD).ClearContents
LastRowA = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRowA
LastRowD = .Cells(.Rows.Count, "D").End(xlUp).Row
Set rng = .Range("D1:D" & LastRowD).Find(.Range("A" & i).Value, LookIn:=xlValues, lookat:=xlWhole)
If Not rng Is Nothing Then
rngColumn = .Cells(rng.Row, .Columns.Count).End(xlToLeft).Column
Cells(rng.Row, rngColumn + 1).Value = .Range("B" & i).Value
Else
.Range("D" & LastRowD + 1).Value = .Range("A" & i).Value
.Range("E" & LastRowD + 1).Value = .Range("B" & i).Value
End If
Next i
End With
End Sub
I think this code will do what you want. Please try it.
Option Explicit
Sub SortToColumns()
' Variatus #STO 30 Jan 2020
Dim WsS As Worksheet ' Source
Dim WsT As Worksheet ' Target
Dim Rng As Range
Dim Fn As String, An As String ' File name, Area name
Dim Rls As Long
Dim Rs As Long
Dim Rt As Long, Ct As Long
With ThisWorkbook ' change as required
Set WsS = .Worksheets("Sheet1") ' change as required
Set WsT = .Worksheets("Sheet2") ' change as required
End With
With WsT
' delete all but the caption row
.Range(.Cells(2, 1), .Cells(.Rows.Count, "A").End(xlUp)).EntireRow.ClearContents
End With
Application.ScreenUpdating = False
With WsS
' find last row of source data
Rls = .Cells(.Rows.Count, "A").End(xlUp).Row
For Rs = 2 To Rls ' start from row 2 (row 1 is caption)
Fn = .Cells(Rs, "A").Value
An = .Cells(Rs, "B").Value
If FileNameRow(Fn, WsT, Rt) Then
' add to existing item
With WsT
Ct = .Cells(Rt, .Columns.Count).End(xlToLeft).Column
Set Rng = .Range(.Cells(Rt, "B"), .Cells(Rt, Ct))
End With
With Rng
Set Rng = .Find(An, .Cells(.Cells.Count), xlValues, xlWhole, xlByRows, xlNext)
End With
' skip if Area exists
If Rng Is Nothing Then WsT.Cells(Rt, Ct + 1).Value = An
Else
' is new item
WsT.Cells(Rt, "A").Value = Fn
WsT.Cells(Rt, "B").Value = An
End If
Next Rs
End With
Application.ScreenUpdating = True
End Sub
Private Function FileNameRow(Fn As String, _
WsT As Worksheet, _
Rt As Long) As Boolean
' Rt is a return Long
' return True if item exists (found)
Dim Fnd As Range
Dim Rng As Range
Dim R As Long
With WsT
R = .Cells(.Rows.Count, "A").End(xlUp).Row
Set Rng = .Range(.Cells(2, "A"), .Cells(R, "A"))
Set Fnd = Rng.Find(Fn, Rng.Cells(Rng.Cells.Count), xlValues, xlWhole, xlByRows, xlNext)
If Fnd Is Nothing Then
Rt = Application.Max(.Cells(.Rows.Count, "A").End(xlUp).Row + 1, 2)
Else
Rt = Fnd.Row
FileNameRow = True
End If
End With
End Function

find text and copy adjacent cell to different sheet

I need help. I need to search my worksheet and find a specific word ("substances"), then copy the value in the cell 2 columns over into a different sheet.
For example, in Sheet1, if "substances" was found in A4, then copy value from C4 and paste into Sheet2 under last filled row. I need to continue doing this for the entire worksheet. "Substances" does not occur sequentially, but always in column A (i.e. the first occurrence may be A4, the ext one might be in A16).
Here's what I have so far:
Dim Cell, cRange As Range
Set cRange = Sheets("Sheet1").Range("A1:A75")
For Each Cell In cRange
FindCounter = 0
If Cell.Value = "Substances" Then
FindCounter = FindCounter + 1
Sheets("Sheet1").Cell.Value(0, 2).Copy
Sheets("Sheet2").Range("A" & Sheets("Sheet2").Cells(Rows.Count, "A").End(xlUp).Row + 1).PasteSpecial xlPasteValues
End If
Next
Application.ScreenUpdating = True
Try this. Find is more efficient than looping (for reasons I have never fully understood).
Sub x()
Dim rFind As Range, s As String
With Sheets("Sheet1").Range("A1:A75")
Set rFind = .Find(What:="Substances", Lookat:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rFind Is Nothing Then
s = rFind.Address
Do
Sheets("Sheet2").Range("A" & Sheets("Sheet2").Cells(Rows.Count, "A").End(xlUp).Row + 1).Value = rFind.Offset(, 2).Value
Set rFind = .FindNext(rFind)
Loop While rFind.Address <> s
End If
End With
End Sub
Alternative using for loop:
Sub Copy()
Dim i As Long
Dim lRow1 As Long, lRow2 As Long
Dim ws1 As Worksheet, ws2 As Worksheet
'set worksheets
Set ws1 = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
'set last row to search for substances
lRow1 = ws1.Range("A" & ws1.Rows.Count).End(xlUp).Row
'start for loop
For i = 1 To lRow1
If ws1.Range("A" & i).Value = "Substances" Then
'assuming you want to paste into column A on sheet 2
'adjust as you need to
lRow2 = ws2.Range("A" & ws2.Rows.Count).End(xlUp).Row + 1
ws2.Range("A" & lRow2).Value = ws1.Range("A" & i).Offset(0, 2).Value
End If
Next
'clear objects
Set ws1 = Nothing
Set ws2 = Nothing
End Sub

Find word in column and copy lines below on different sheet

I have source data which are not aligned to table.
I want to find text (e.g. Account), copy the two whole lines below the cell with the found text (Account) and paste them on a different Sheet. Then search down and do again until the data ends. Data should be pasted in the order it is reached.
The cell with word "Account" will be always in the column A. The search should be for the exact word "Account", because in the column can be cells which contain e.g. "Payer account".
This code shows me an error msg
"Run-time error 438 - object doesnt support this property or method"
Private Sub Search_n_Copy()
Dim LastRow As Long
Dim rng As Range, C As Range
With Worksheets("INPUT_2") ' <-- here should be the Sheet's name
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' last row in column A
Set rng = .Range("A1:A" & LastRow) ' set the dynamic range to be searched
' loop through all cells in column A and copy below's cell to sheet "Output_2"
For Each C In rng
If C.Value = "Account" Then
C.Offset(-1, 0).Copy C.Offset.OUTPUT_2(-7, -1) ' use offset to put value in sheet "Output_2", column E
End If
Next C
End With
End Sub
This post doesn't point out what the error in your original code is. Ron Rosenfeld has already covered that in the comment.
Here is another faster way (as compared to looping) which uses .Find/.FindNext to achieve what you want. It also doesn't copy the rows in a loop but copies in the end.
Private Sub Search_n_Copy()
Dim ws As Worksheet
Dim rngCopy As Range, aCell As Range, bcell As Range
Dim strSearch As String
strSearch = "Account"
Set ws = Worksheets("INPUT_2")
With ws
Set aCell = .Columns(1).Find(What:=strSearch, LookIn:=xlValues, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bcell = aCell
If rngCopy Is Nothing Then
Set rngCopy = .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2))
Else
Set rngCopy = Union(rngCopy, .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2)))
End If
Do
Set aCell = .Columns(1).FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bcell.Address Then Exit Do
If rngCopy Is Nothing Then
Set rngCopy = .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2))
Else
Set rngCopy = Union(rngCopy, .Rows((aCell.Row + 1) & ":" & (aCell.Row + 2)))
End If
Else
Exit Do
End If
Loop
Else
MsgBox SearchString & " not Found"
End If
'~~> I am pasting to Output sheet. Change as applicable
If Not rngCopy Is Nothing Then rngCopy.Copy Sheets("Output").Rows(1)
End With
End Sub
Screenshot
The codle would be like this. This code Use variant.
Private Sub Search_n_Copy()
Dim LastRow As Long
Dim rng As Range, C As Range
Dim vR(), n As Long, k As Integer, j As Integer
Dim Ws As Worksheet
With Worksheets("INPUT_2") ' <-- here should be the Sheet's name
.Columns("e").ClearContents
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' last row in column A
Set rng = .Range("A1:A" & LastRow) ' set the dynamic range to be searched
' loop through all cells in column A and copy below's cell to sheet "Output_2"
For Each C In rng
If C.Value = "Account" Then
For j = 1 To 2
n = n + 1
ReDim Preserve vR(1 To 6, 1 To n)
For k = 1 To 6
vR(k, n) = C.Offset(j, k - 1) ' use offset to put value in sheet "Output_2", column E
Next k
End If
Next C
If n > 0 Then
Set Ws = Sheets.Add '<~~~ Sheets("your sheet name")
With Ws
.Range("a1").Resize(n, 6) = WorksheetFunction.Transpose(vR)
End With
End If
End With
End Sub

Input box to paste found rows to new sheet

I have what is working code but I want to be able to run it 2,3, 4 times and have it just keep moving down the destination sheet. Instead it overwrites what the last pass pasted.
Sub Comparison_Entry()
Dim myWord$
myWord = InputBox("Enter UID, If no more UIDs, enter nothing and click OK", "Enter User")
If myWord = "" Then Exit Sub
Application.ScreenUpdating = False
Dim xRow&, NextRow&, LastRow&
NextRow = 1
LastRow = Cells.Find(What:="*", After:=Range("A1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
For xRow = 1 To LastRow
If WorksheetFunction.CountIf(Rows(xRow), "*" & myWord & "*") > 0 Then
Rows(xRow).Copy Sheets("Sheet1").Rows(NextRow)
NextRow = NextRow + 1
End If
Next xRow
Application.ScreenUpdating = True
MsgBox "Copyng complete, " & NextRow - 2 & " rows containing" & vbCrLf & _
"''" & myWord & "''" & " were copied to Sheet1.", 64, "Done"
End Sub``
I tried adding a loop to this but each pass through it would start over at the top of Sheet1. Similarly, if I simply call the Sub again I get the same result.
Normally you would know what column to search through, such as what column is UID. in this example code I will assume it is column A of the active sheet, change the column letter to what suites you.
Sub Comparison_EntryB()
Dim Rws As Long, rng As Range, c As Range
Dim ws As Worksheet, sh As Worksheet, s As String
Set ws = ActiveSheet
Set sh = Sheets("Sheet1")
With ws
Rws = .Cells(.Rows.Count, "A").End(xlUp).Row 'change to column you need you search through
Set rng = .Range(.Cells(1, "A"), .Cells(Rws, "A")) 'change to column you need to search through
End With
s = InputBox("enter Something")
For Each c In rng.Cells
If UCase(c) Like "*" & UCase(s) & "*" Then
c.EntireRow.Copy sh.Cells(sh.Rows.Count, "A").End(xlUp).Offset(1)
End If
Next c
End Sub

Looping through columns to find search criteria and paste cell values from another sheet beneath the criteria

The workbook contains three sheets:
Item-style (contains in colA the item no., colB the style of the item)
Style (List of styles we want)
Style template (List of items within the styles specified in the cols)
I need a macro that does three things:
Copy the list of styles from the Style sheet and paste & transpose in Style template starting from row 2. Row 1 of all columns needs to be left blank.
The macro needs to select each style in style template one by one, which is now in different columns. These will be the search criteria.
On the basis of style selected in step 2, the macro needs to do a search in item-style sheet and select all the items that have the selected style and paste all these items beneath the corresponding style in style-template sheet. If there are no items corresponding to the selected style, then it should mention "No items" beneath the corresponding style.
Here's a link to the workbook for easy understanding
StyleProject
Though the workbook mentions only three styles the macro should have the capability of working with more than 50 styles.
Here's the code I have:
Sub StyleProject()
Application.ScreenUpdating = False
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Set ws = Sheets("Item-Style")
Set ws2 = Sheets("Style")
Set ws3 = Sheets("Style Template")
Dim rng As Range, secRng As Range
Dim i, j, k
Sheets("Style Template").Activate
finalcol = Cells(2, 50).End(x1toleft).Column
For i = 2 To finalcol
j = Cells(2, i).Value
lr = ws.Range("A" & Rows.Count).End(xlUp).Row
For k = 2 To lr
Set rng = ws.Range("B" & i)
If StrComp(CStr(rng.Text), j, 1) = 0 Then
ws.Rows(k & ":" & k).Copy
nxtRow = ws3.Range(i & Rows.Count).End(xlUp).Row + 1
ws2.Rows(nxtRow & ":" & nxtRow).PasteSpecial Paste:=xlPasteValues, _
Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Set rng = Nothing
End If
Next k
Next i
Application.ScreenUpdating = True
End Sub
It ends up in error trying to figure out nextrng I believe.
Sub StyleProject()
Dim wsStyle As Worksheet
Dim wsData As Worksheet
Dim wsTemplate As Worksheet
Dim StyleCell As Range
Dim rngFound As Range
Dim arrResults() As Variant
Dim strFirst As String
Dim ResultIndex As Long
Dim StyleIndex As Long
Set wsStyle = Sheets("Style")
Set wsData = Sheets("Item Data")
Set wsTemplate = Sheets("Style Template")
With wsStyle.Range("A2", wsStyle.Cells(Rows.Count, "A").End(xlUp))
If .Row < 2 Then Exit Sub 'No data
ReDim arrResults(1 To 1 + Evaluate("MAX(COUNTIF(" & wsData.Columns("B").Address(External:=True) & "," & .Address(External:=True) & "))"), 1 To .Cells.Count)
For Each StyleCell In .Cells
StyleIndex = StyleIndex + 1
ResultIndex = 1
arrResults(ResultIndex, StyleIndex) = StyleCell.Text
Set rngFound = wsData.Columns("B").Find(StyleCell.Text, wsData.Cells(Rows.Count, "B"), xlValues, xlWhole)
If Not rngFound Is Nothing Then
strFirst = rngFound.Address
Do
ResultIndex = ResultIndex + 1
arrResults(ResultIndex, StyleIndex) = wsData.Cells(rngFound.Row, "A").Text
Set rngFound = wsData.Columns("B").Find(StyleCell.Text, rngFound, xlValues, xlWhole)
Loop While rngFound.Address <> strFirst
End If
Next StyleCell
End With
If UBound(arrResults, 1) > 1 Then
wsTemplate.Range("B2", wsTemplate.Cells(Rows.Count, Columns.Count)).Clear
wsTemplate.Range("B2").Resize(UBound(arrResults, 1), UBound(arrResults, 2)).Value = arrResults
With wsTemplate.Range("B2").Resize(, UBound(arrResults, 2))
.Font.Bold = True
.Borders(xlEdgeBottom).LineStyle = xlContinuous
.EntireColumn.AutoFit
End With
End If
Set wsStyle = Nothing
Set wsData = Nothing
Set wsTemplate = Nothing
Set StyleCell = Nothing
Set rngFound = Nothing
Erase arrResults
End Sub

Resources