Comparing Two Workbooks and Deleting Matched Rows - vba

I am trying to compare two workbooks but unlikely upon Running the Macro, getting Error
"Subscript Out of the Range".
Can anyone please help in Removing the Error? Thanks
Sub CompInTwoWorkbooks()
Dim wb1 As Workbook, wb2 As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Dim c As Range, rng As Range
Dim lnLastRow1 As Long, lnLastRow2 As Long
Dim lnTopRow1 As Long, lnTopRow2 As Long
Dim lnCols As Long, i As Long
Set wb1 = Workbooks("listeappli.xlsx") 'Adjust as required
Set wb2 = Workbooks("Keyword.xlsx") 'Adjust as required
Set ws1 = wb1.Sheets("listeappli") 'Adjust as required
Set ws2 = wb2.Sheets("Keyword") 'Adjust as required
lnTopRow1 = 2 'first row containing data in wb1 'Adjust as required
lnTopRow2 = 2 'first row containing data in wb2 'Adjust as required
'Find last cells containing data:
lnLastRow1 = ws1.Range("M:M").Find("*", Range("M1"), LookIn:=xlValues, searchdirection:=xlPrevious).Row
lnLastRow2 = ws2.Range("A:A").Find("*", Range("A1"), LookIn:=xlValues, searchdirection:=xlPrevious).Row
Set rng = ws2.Range("A" & lnTopRow2 & ":A" & lnLastRow2)
lnCols = ws1.Columns.Count
ws1.Columns(lnCols).Clear 'Using the very right-hand column of the sheet
For i = lnLastRow1 To lnTopRow1 Step -1
For Each c In rng
If ws1.Range("M" & i).Value = c.Value Then
ws1.Cells(i, lnCols).Value = "KEEP" 'Add tag to right-hand column of sheet if match found
Exit For
End If
Next c
Next i
'Delete rows where the right-hand column of the sheet is blank
Set rng = ws1.Range(Cells(lnTopRow1, lnCols), Cells(lnLastRow1, lnCols))
rng.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
ws1.Columns(lnCols).Clear
End Sub

If your workbook is not open already and you want the macro to open it automatically you must use the Workbooks.Open Method.
use the following if listeappli.xlsx is in the same path as the actual file
Set wb1 = Workbooks.Open(Filename:=ThisWorkbook.Path & Application.PathSeparator & "listeappli.xlsx")
or specify the full path for Filename:= like
Set wb1 = Workbooks.Open(Filename:="C:\MyFolder\listeappli.xlsx")

Related

Determine Range/Conditions for Copy/Paste Procedure

I need help defining my copy/paste process. I just need an example for the two conditions. The situation is as follows:
I need to search for for specific keywords in a sheet of wb1 and
copy/paste it to wb2 under certain conditions.
I dont know the specific sheet or the position of the keywords, so
every sheet in the wb should be checked
In case a keyword is found - condition 1 or condition 2 will be
applied, depending on the keyword:
Condition 1: if keyword in wb1 = "mx1" then copy/paste keyword to wb2
(specific position -> Sheet2, K7) and rename it to "Male". Result
would be: "Male" in K7 of Sheet2 in wb2.
Condition 2: if keyword in wb1 = "Data 1" then copy the
value(integer) of the adjoining cell to the right of it and paste to
wb2 (specific position -> Sheet3, K3). Result would be: "189" in K7
of Sheet3 in wb2.
A keyword can only have one of the conditions assigned.
Actually, my goal is to have a set of keywords, which have condition
1 or condition 2 assigned, as well as a specific paste-location in
wb2. So, every sheet should be checked according to the set of
keywords.
Example:
https://imgur.com/a/8VCNsrC
Would appreciate any help!
Code so far - only thing I need is condition 1 and 2....
Public Sub TransferFile(TemplateFile As String, SourceFile As String)
Dim wbSource As Workbook
Set wbSource = Workbooks.Open(SourceFile) 'open source
Dim rFnd As Range
Dim r1st As Range
Dim ws As Worksheet
Dim arr(1 To 2) As Variant
Dim i As Long
Dim wbTemplate As Workbook
Dim NewWbName As String
Dim wsSource As Worksheet
For Each wsSource In wbSource.Worksheets 'loop through all worksheets in source workbook
Set wbTemplate = Workbooks.Open(TemplateFile) 'open new template
'/* Definition of the value range */
arr(1) = "mx1"
arr(2) = "Data 1"
For i = LBound(arr) To UBound(arr)
For Each ws In ThisWorkbook.Worksheets
Debug.Print ws.Name
Set rFnd = ws.UsedRange.Find(what:=arr(i), LookIn:=xlValues, lookat:=xlPart, SearchOrder:=xlRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not rFnd Is Nothing Then
Set r1st = rFnd
Do
If i = 1 Then
wb2.Sheets("Sheet1").Range("A3").Value = "Male"
Else
wb2.Sheets("Sheet1").Range("B3").Value = rFnd.Offset(0, 1).Value
End If
Set rFnd = ws.UsedRange.FindNext(rFnd)
Loop Until r1st.Address = rFnd.Address
End If
Next
Next
NewWbName = Left(wbSource.Name, InStr(wbSource.Name, ".") - 1)
wbTemplate.SaveAs wbSource.Path & Application.PathSeparator & NewWbName & "_New.xlsx"
wbTemplate.Close False 'close template
Next wsSource
wbSource.Close False 'close source
End Sub
You can search a Range for a value, and a range applies to a (part of a) single sheet. So you need to search each worksheet separately. Similarly, you search for a single value, so in this case you need to issue 2 separate searches. I'd do it this way:
Dim rFnd As Range
Dim r1st As Range
Dim ws As Worksheet
Dim arr(1 to 2) As Variant
Dim i as Long
arr(1) = "mx1"
arr(2) = "Data 1"
For i = Lbound(arr) to Ubound(arr)
For Each ws In ThisWorkbook.Worksheets
Debug.Print ws.Name
Set rFnd = ws.UsedRange.Find(what:=arr(i), LookIn:=xlValues, lookat:=xlPart, SearchOrder:=xlRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not rFnd Is Nothing Then
Set r1st = rFnd
Do
If i = 1 then
wb2.Sheets("Sheet2").Range("K7").Value = "Male"
Else
wb2.Sheets("Sheet3").Range("K3").Value = rFnd.Offset(0, 1).Value
End If
Set rFnd = ws.UsedRange.FindNext(rFnd)
Loop Until r1st.Address = rFnd.Address
End If
Next
Next

Copy data from one sheet to the last row of another sheet

I'm trying to copy the data from one sheet to the last row of another sheet.
The reason why I am doing this is because I want to consolidate the data in a sheet which is already existing and my contain already a data.
Below is my code so far which only copies again to the A2 of another sheet. What approach should I do for this:
Sub Upload()
Dim Wb1 As Workbook
Dim Wb2 As Workbook
Dim MainPage As Worksheet
Set MainPage = Sheets("Main")
Dim r As Long
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Set Wb1 = ActiveWorkbook
FileToOpen = Application.GetOpenFilename _
(Title:="Please choose a File", _
filefilter:="Excel File *.xlsx (*.xlsx),")
If FileToOpen = False Then
MsgBox "No File Specified.", vbExclamation, "ERROR"
Exit Sub
Else
Set Wb2 = Workbooks.Open(Filename:=FileToOpen)
With Wb2.Sheets("ALL TICKETS (excpt Open-OnHold)")
srcLastRow = .Range("A:AJ").Find("*", SearchOrder:=xlByRows,
SearchDirection:=xlPrevious).Row
destLastRow = Wb1.Sheets("ALL TICKETS (excpt Open-OnHold)".Range("A:AJ").Find("*", SearchOrder:=xlByRows,
SearchDirection:=xlPrevious).Row + 1
Wb1.Sheets("ALL TICKETS (excpt Open-OnHold)").Range("A2:AJ" &
destLastRow).Value = .Range("A2", "AJ" & srcLastRow).Value
End With
Wb2.Close
End If
End Sub
You know your copied range, so then you need to know the last row of the destination sheet:
dim lr as long
With Sheets("Destination")
lr = .cells(.rows.count,1).end(xlup).row 'assumes column 1 is contiguous
End with
You can then take your source range (will use variable SrcRng) and paste to the new sheet, into a specific cell:
SrcRng.Copy Sheets("Destination").Cells(lr+1,1) 'this line does the copy and the paste
The rest of the copied range will be filled in.
Edit1:
Hard to show the code in a comment...
Dim LRSrc as Long, LRDest as Long, SrcRng as Range
With Sheets("Source")
LRSrc = .cells(.rows.count,1).end(xlup).row 'assumes column 1 is contiguous
Set SrcRng = .Range("A1:AJ" & LRSrc)
End with
With Sheets("Destination")
LRDest = .cells(.rows.count,1).end(xlup).row 'assumes column 1 is contiguous
SrcRng.Copy .Cells(LRDest+1,1)
End with
Would this work for you.
defining srcLastRow as below.
srcLastRow = Cells(Rows.Count, 36).End(xlUp).Row

Excel VBA: How do I create a search engine using VBA that takes a cell's row and copies it onto a new tab within the same worksheet?

I'm trying to make excel focus on the cell that contains what I've searched. So if the cell is out of view in my excel spreadsheet after the search the screen auto adjusts to that specific cell. Then, I need to take everything in that cell's row and have it automatically copy into a new tab within the same excel spreadsheet. But the rows copied in the second tab need to start with Column A in row #5 and continue on. Below is the code I have so far, I'm not too familiar with VBA but I've been working at it. Any help or insight would be greatly appreciated.
`Option Explicit
Sub FindWhat()
Dim sFindWhat As String
Dim sh1 As Worksheet
Dim sh2 As Worksheet
Dim sh3 As Worksheet
Dim Search As Range
Dim Addr As String
Dim NextRow As Long
Dim cl As Range
Set sh1 = ThisWorkbook.Sheets("Sheet1")
Set sh2 = ThisWorkbook.Sheets("Sheet2")
Set sh3 = ThisWorkbook.Sheets("Sheet3")
'// This will be the row you start pasting data on Sheet3
NextRow = 5
For Each cl In Intersect(sh1.UsedRange, sh1.Columns("A")).Cells
'// the value we're looking for
sFindWhat = cl.Value
'// Find this value in Sheet2:
With sh2.UsedRange
Set Search = .Find(sFindWhat, LookIn:=xlValues,
SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Search Is Nothing Then
'// Get out of here if the value is not found
'// Do NOT Exit the sub, we'll just proceed to next cell in column A
'Exit Sub
Else
'// Make sure next row in Sh3.Column("K") is empty
While sh3.Range("K" & NextRow).Value <> ""
NextRow = NextRow + 1
Wend
'// Paste the row in column K of sheet 3:
Search.Resize(1, 12).Copy Destination:=sh3.Range("K" & NextRow)
End If
End With
Next
End Sub
Try that:
Dim sh1 As Worksheet
Dim sh2 As Worksheet
Dim sh3 As Worksheet
Dim rng As Range
Dim IdRng As Range
Dim SrcRng As Range
Dim Search As Range
Dim lRow1 As Long
Dim lRow2 As Long
Dim lRow3 As Long
Set sh1 = ThisWorkbook.Sheets("Plan1")
Set sh2 = ThisWorkbook.Sheets("Plan2")
Set sh3 = ThisWorkbook.Sheets("Plan3")
lRow1 = sh1.Range("A" & Rows.Count).End(xlUp).Row
If lRow1 < 4 Then lRow1 = 4
Set IdRng = sh1.Range("A4:A" & lRow1) 'Dynamic ID's Range
lRow2 = sh2.Range("L" & Rows.Count).End(xlUp).Row
If lRow2 < 4 Then lRow2 = 4
Set SrcRng = sh2.Range("L3:L" & lRow2) 'Dynamic sheet2 search range
For Each rng In IdRng
Set Search = SrcRng.Find(What:=rng, LookIn:=xlValues)
If Not Search Is Nothing Then
lRow3 = sh3.Range("K" & Rows.Count).End(xlUp).Row
If lRow3 < 5 Then lRow3 = 5
sh2.Range(Search.Address).EntireRow.Copy sh3.Range("K" & lRow3) 'dynamic paste range
Else
MsgBox rng & " was not found.", vbInformation, sh1.Name
End If
Next rng
Remember to change Set sh1 = ThisWorkbook.Sheets("Plan1"), Set sh2 = ThisWorkbook.Sheets("Plan2") and Set sh3 = ThisWorkbook.Sheets("Plan3") to the name of your sheets.
This code has dynamic ranges for your Id's column (sheet1), search's column (sheet2) and paste's column (sheet3), so it will identify automatically in which range the last data is.

excel 2013 vba, how to use a loop to move data between workbooks based on unique identifier

I want to copy data from one workbook to another based on a shared unique identifier. I would like to loop through the cells in Column BP in Workbook 1, starting with Row 4, finding the matching cell value in Column BQ, starting with Row 6, of Workbook 2 and copying data associated that unique identifier from Workbook 2 to Workbook 1. My code is below, I'm getting a 'subscript out of range' error. I think it has to do with my DataCopy and DataPaste ranges, I want them to refer to the Row of the unique identifier in the for loop. I would appreciate any pointers that get me moving along. Thanks.
Sub cmdUpdate_Click()
Dim LastRow As Long
Dim Key1 As Range, Key2 As Range, DataCopy As Range, DataPaste As Range, Cell As Range, Cell2 As Range
Dim wb1 As Workbook, wb2 As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
Set wb1 = Workbooks("File Name")
Set wb2 = Workbooks.Open("File Path", ReadOnly:=True)
Set ws1 = wb1.Sheets("Sheet1")
Set ws2 = wb2.Sheets("Sheet1")
LastRow = xlLastRow
Set Key1 = ws1.Range("BP6:BP" & LastRow)
Set Key2 = ws2.Range("BQ4:BQ" & LastRow)
Set DataCopy = ws2.Range("P:BK")
Set DataCopy = ws1.Range("P:BK")
For Each Cell In Key1
Set Cell2 = Key2.Find(what:=Cell.Value, LookIn:=xlValues)
If Not Cell2 Is Nothing Then
Rows.Range(DataCopy).Copy
Rows.Range(DataPaste).PasteSpecial Paste:=xlPasteValues
End If
Next
End Sub
Function xlLastRow(Optional WorksheetName As String) As Long
' find the last populated row in a worksheet
If WorksheetName = vbNullString Then WorksheetName = ActiveSheet.Name
With Worksheets(WorksheetName)
On Error Resume Next
xlLastRow = .Cells.Find("*", .Cells(1), xlFormulas, _
xlWhole, xlByRows, xlPrevious).Row
If Err <> 0 Then xlLastRow = 0
End With
End Function

Copy rows starting from certain row till the end using macro

I need to copy values of one excel and create a new one with required format. Say i need to copy columns from B11 to BG11 and rows will be till the end.( i don't know how to find the end of rows). And I have column heading in b7 to bg7. In between there are unwanted rows and i don't need it. So in the new excel i want column headings(which is from b7 to bg7) as first row and the values from b11 to bg11 till the end.
This is my first excel Macro. I don't know how to proceed. So with references from some stackoverflow question and other site, i have tried the below code. but it is not giving the required output.
Sub newFormat()
Dim LastRow As Integer, i As Integer, erow As Integer
LastRow = ActiveSheet.Range(“B” & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
Sheets("MySheetName").Range("B7:BG7").Copy
Sheets("MySheetName").Range("B11:BG11").Copy
Workbooks.Open Filename:=”C:\Users\abcd\Documents\Newformat.xlsx”
Worksheets(“Sheet1”).Select
erow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ActiveSheet.Cells(erow, 1).Select
ActiveSheet.Paste
ActiveWorkbook.Save
ActiveWorkbook.Close
Application.CutCopyMode = False
End If
Next i
End Sub
this may be simple. any help would be appreciated.
Few things...
Do not use Integer for rows. Post xl2007, the number of rows have increased and Integer can't hold that. Use Long
You do not need to select a range to paste on it. You can directly perform the action.
You do not need to use a loop. You can copy ranges in two chunks
Work with objects so Excel doesn't get confused by your objects.
Since Sheet1 is empty, you don't need to find the last row there. Simply start at 1.
To output the data to new workbook, you have to use Workbooks.Add
See this example (Untested)
Sub newFormat()
Dim wbO As Workbook
Dim wsI As Worksheet, wsO As Worksheet
Dim LastRow As Long, erow As Long
'~~> Set this to the relevant worksheet
Set wsI = ThisWorkbook.Sheets("HW SI Upload")
'~~> Find the last row in Col B
LastRow = wsI.Range("B" & wsI.Rows.Count).End(xlUp).Row
'~~> Open a new workbook
Set wbO = Workbooks.Add
'~~> Set this to the relevant worksheet
Set wsO = wbO.Sheets(1)
'~~> The first row in Col A for writing
erow = 1
'~~> Copy Header
wsI.Range("B7:BG7").Copy wsO.Range("A" & erow)
'~~> Increment output row by 1
erow = erow + 1
'~~> Copy all rows from 11 to last row
wsI.Range("B11:BG" & LastRow).Copy wsO.Range("A" & erow)
'~~> Clear Clipboard
Application.CutCopyMode = False
'
'~~> Code here to do a Save As
'
End Sub
Different but the same
Rename the sheet
Sub Button1_Click()
Dim wb As Workbook, ws As Worksheet, sh As Worksheet
Dim LstRw As Long, Rng As Range, Hrng As Range
Set sh = Sheets("MySheetName")
With sh
Set Hrng = .Range("B7:BG7")
LstRw = .Cells(.Rows.Count, "B").End(xlUp).Row
Set Rng = .Range("B11:BG" & LstRw)
End With
Application.ScreenUpdating = 0
Workbooks.Open Filename:="C:\Users\abcd\Documents\Newformat.xlsx"
Set wb = Workbooks("Newformat.xlsx")
Set ws = wb.Sheets(1)
Hrng.Copy ws.Cells(Rows.Count, "A").End(xlUp).Offset(1)
Rng.Copy ws.Cells(Rows.Count, "A").End(xlUp).Offset(1)
ws.Name = sh.Name 'renames sheet
wb.Save
wb.Close
End Sub