There are two Excel workbooks, Master and Survey Responses.
I have to loop through each row in Survey Responses, to select the value from the 4th column and compare it to the 4th column in Master. If there is no match then copy the complete row from Survey Responses to the end of Master. For the first time there will be no rows in Master so all rows must be copied from Survey Responses.
Survey Responses
The below code does not loop through all rows and if I run it a second time it copies all rows without performing the comparison.
'''''Define Object for Target Workbook
Dim Target_Workbook As Workbook
Dim Source_Workbook As Workbook
Dim Source_Path As String
'''''Assign the Workbook File Name along with its Path
Source_Path = "C:\Users\Survey Responses\Survey Response.xls"
Set Source_Workbook = Workbooks.Open(Source_Path)
Set Target_Workbook = ThisWorkbook
'''''With Source_Workbook object now, it is possible to pull any data from it
'''''Read Data from Source File
'''''Logic to select unique rows only
Dim rngSource As Range, rngTarget As Range, cellSource As Range, cellTarget As Range
Set rngSource = Source_Workbook.Sheets(1).Range("Responses")
Set rngTarget = Target_Workbook.Sheets(2).Range("Responses")
Dim rowNr_target As Integer, Rng As Range
With Target_Workbook.Sheets(2)
rowNr_target = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Dim counter As Integer, found As Boolean, inner_counter As Integer
counter = 1
For Each cellSource In rngSource.Rows
'On Error Resume Next
If cellSource.Cells(counter, 1).Value = "" Then
Exit For
End If
found = False
inner_counter = 1
For Each cellTarget In rngTarget.Rows
If cellTarget.Cells(inner_counter, 1).Value = "" Then
Exit For
End If
''''test = Application.WorksheetFunction.VLookup(test1, rngTarget, 1, False)
If (cellSource.Cells(counter, 4) = cellTarget.Cells(inner_counter, 4)) Then
found = True
Exit For
End If
inner_counter = inner_counter + 1
Next
If (found = False) Then
cellSource.EntireRow.Copy
If (rowNr_target > 1) Then
rngTarget.Rows(rowNr_target + 1).Insert
Else
rngTarget.Rows(rowNr_target).Insert
End If
rowNr_target = rowNr_target + 1
End If
counter = counter + 1
'On Error GoTo 0
Next
'''''Target_Workbook.Sheets(2).Range("Responses").Value = Source_data
'''''Close Target Workbook
Source_Workbook.Save
Target_Workbook.Save
''''Source_Workbook.Close False
'''''Process Completed
MsgBox "Task Completed"
Updated code:
Dim cel As Range
Dim rng As Range
Dim r As Range
Dim lastrow As Long
Dim Target_Workbook As Workbook
Dim Source_Workbook As Workbook
Dim Source_Path As String
'''''Assign the Workbook File Name along with its Path
Source_Path = "C:\Users\Survey Responses\Survey Response.xls"
Set Source_Workbook = Workbooks.Open(Source_Path)
Set Target_Workbook = ThisWorkbook
Dim rngSource As Range, rngTarget As Range, cellSource As Range, cellTarget As Range
Set rngSource = Source_Workbook.Sheets(1).Range("Responses")
Set rngTarget = Target_Workbook.Sheets(2).Range("Responses")
With Target_Workbook.Sheets(2)
lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row
For Each cel In Source_Workbook.Sheets(1).Range("D:D")
If cel.Value = "" Then
Exit For
End If
Set r = .Range("D:D").Find(What:=cel, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If r Is Nothing Then
cel.EntireRow.Copy
rngTarget.Rows(lastrow).Insert
''If Not rng Is Nothing Then Set rng = Union(rng, cel) Else Set rng = cel
End If
Next cel
''rng.Copy.Range("A" & lastrow).PasteSpecial xlPasteValues
End With
'''''Close Target Workbook
Source_Workbook.Save
Target_Workbook.Save
''''Source_Workbook.Close False
'''''Process Completed
MsgBox "Task Completed"
This is untested code but it should help you with anything you already have. You will need to adjust the ranges to suit yourself, but it will loop through one sheet and collect values that dont exists and then copy them to another sheet.
Try this,
Sub dave()
Dim cel As Range
Dim rng As Range
Dim r As Range
Dim lastrow As Long
With Sheets("Master")
lastrow = .Cells(.Rows.Count, 1).End(xlUp).Row
For Each cel In Sheets("Sheet1").Range("D1:D22")
Set r = .Range("D:D").Find(What:=cel, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If r Is Nothing Then
If Not rng Is Nothing Then Set rng = Union(rng, cel) Else Set rng = cel
End If
Next cel
rng.Copy
.Range("A" & lastrow).PasteSpecial xlPasteValues
End With
End Sub
Related
Tried doing a search tool to the excel sheet (VBA) I'm working on.
So far every time I search for the text, it ends up filtering only the first row and not any row that has the value I'm looking for. I added a picture to show what it returns and the code as well. Is there anything I need to change to the code to make it search for all the data in the sheet instead of having it to show only one row? Any help is appreciated.
Search result of only the first row:
Sub SearchAllSheets()
Dim ws As Worksheet, OutputWs As Worksheet
Dim rFound As Range
Dim strName As String
Dim count As Long, LastRow As Long
Dim IsValueFound As Boolean
IsValueFound = False
Set OutputWs = Worksheets("sheet1") '---->change the sheet name as required
LastRow = OutputWs.Cells(Rows.count, "A").End(xlUp).Row
On Error Resume Next
strName = InputBox("What are you looking for?")
If strName = "" Then Exit Sub
For Each ws In Worksheets
If ws.Name <> "Output" Then
With ws.UsedRange
Set rFound = .Find(What:=strName, After:=.Cells(1, 1), LookIn:=xlValues, LookAt:=xlWhole)
If Not rFound Is Nothing Then
Application.Goto rFound, True
IsValueFound = True
'MsgBox rFound.Row
rFound.EntireRow.Copy
OutputWs.Cells(LastRow + 1, 1).PasteSpecial xlPasteAll
Application.CutCopyMode = False
LastRow = LastRow + 1
End If
End With
End If
Next ws
On Error GoTo 0
If IsValueFound Then
OutputWs.Select
MsgBox "Result pasted to Sheet Output"
Else
MsgBox "Value not found"
End If
End Sub
Try this:
Sub SearchAllSheets()
Dim ws As Worksheet, OutputWs As Worksheet
Dim rFound As Range, IsValueFound As Boolean
Dim strName As String
Dim count As Long, LastRow As Long
Set OutputWs = Worksheets("Output") '---->change the sheet name as required
LastRow = OutputWs.Cells(Rows.count, "A").End(xlUp).row
strName = Trim(InputBox("What are you looking for?"))
If strName = "" Then Exit Sub
For Each ws In Worksheets
If ws.Name <> OutputWs.Name Then
Debug.Print "Checking " & ws.Name
Set rFound = FindAll(ws.UsedRange, strName)
If Not rFound Is Nothing Then
Set rFound = rFound.EntireRow
count = rFound.Cells.count / Columns.count 'how many matched rows?
Debug.Print "Found " & count & " rows"
rFound.Copy OutputWs.Cells(LastRow + 1, 1)
LastRow = LastRow + count
IsValueFound = True
End If
End If
Next ws
If IsValueFound Then
OutputWs.Select
MsgBox "Result(s) pasted to Sheet " & OutputWs.Name
Else
MsgBox "Value not found"
End If
End Sub
'find all cells in range `rng` with value `val` and return as a range
Public Function FindAll(rng As Range, val As String) As Range
Dim rv As Range, f As Range
Dim addr As String
Set f = rng.Find(what:=val, After:=rng.Cells(rng.Cells.count), _
LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not f Is Nothing Then addr = f.Address()
Do Until f Is Nothing
If rv Is Nothing Then
Set rv = f
Else
Set rv = Application.Union(rv, f)
End If
Set f = rng.FindNext(After:=f)
If f.Address() = addr Then Exit Do
Loop
Set FindAll = rv
End Function
I need help modifying the code below to look through the entire workbook searching for "$" instead of just one. I would love it if it could just search for CGYSR-"##". I have had help putting the code together as I am new to VBA
Here is the code:
Option Explicit
Sub FindPriceTagInformation()
Dim FirstAddress As String
Dim MyArr As Variant
Dim Rng As Range
Dim Rcount As Long
Dim I As Long
Dim NewSh As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Fill in the search Value
MyArr = Array("$")
Set NewSh = Sheets("Sheet2")
With Sheets("CGYSR-3").Range("A1:ZZ300")
Rcount = 0
For I = LBound(MyArr) To UBound(MyArr)
Set Rng = .Find(What:=MyArr(I), _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rcount = Rcount + 1
NewSh.Cells(Rcount, 3).Value = Rng.Value
NewSh.Cells(Rcount, 2).Value = Rng.Offset(-3, 0).Value
NewSh.Cells(Rcount, 1).Value = Rng.Offset(-5, 0).Value
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Please, try the next adapted code:
Sub FindPriceTagInformation()
Dim FirstAddress As String, MyArr, Rng As Range, Rcount As Long, I As Long
Dim ws As Worksheet, NewSh As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Fill in the search Value
MyArr = Array("$")
Set NewSh = Sheets("Sheet2")
Rcount = 0
For Each ws In ActiveWorkbook.Sheets
If left(ws.Name, 6) = "CGYSR-" Then
With ws.Range("A1:ZZ300")
For I = LBound(MyArr) To UBound(MyArr)
Set Rng = .Find(What:=MyArr(I), _
After:=.cells(.cells.count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
FirstAddress = Rng.Address
Do
Rcount = Rcount + 1
NewSh.cells(Rcount, 3).value = Rng.value
NewSh.cells(Rcount, 2).value = Rng.Offset(-3, 0).value
NewSh.cells(Rcount, 1).value = Rng.Offset(-5, 0).value
Set Rng = .FindNext(Rng)
Loop While Not Rng Is Nothing And Rng.Address <> FirstAddress
End If
Next I
End With
End If
Next ws
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Searching in Worksheets
In the workbook containing this code (ThisWorkbook), loops through each worksheet trying to identify the ones whose name starts with a given string (CGYSR-). Then it searches for a $ identifying cells with prices and retrieves these cell's values and the values of two other associated cells (3 and 5 cells above) and writes them to a row in another worksheet (Sheet2).
Option Explicit
Sub FindPriceTagInformation()
Const swsNameBegin As String = "CGYSR-"
Const srgAddress As String = "A1:ZZ300"
Const dwsName As String = "Sheet2"
Dim SearchStrings As Variant: SearchStrings = Array("$")
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Destination Worksheet
Dim dws As Worksheet: Set dws = wb.Worksheets(dwsName)
' You do it once here, so you don't have to do it many times in the loops.
Dim sCellsCount As Long: sCellsCount = dws.Range(srgAddress).Cells.Count
Dim npLen As String: npLen = Len(swsNameBegin)
Dim ssLower As Long: ssLower = LBound(SearchStrings)
Dim ssUpper As Long: ssUpper = UBound(SearchStrings)
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Dim sws As Worksheet ' Source Worksheet
Dim srg As Range ' Srouce Range
Dim sfCell As Range ' Source Found Cell
Dim slCell As Range ' Source Last Cell
Dim dr As Long ' Current Destination Row
Dim ss As Long ' Current Search String
Dim FirstAddress As String
For Each sws In wb.Worksheets
' A 'begins-with' ('Left') comparison where 'StrComp' will return 0 if
' the strings are equal. Combined with 'vbTextCompare', it will
' ignore case i.e. 'CG=cg'.
If StrComp(Left(sws.Name, npLen), swsNameBegin, vbTextCompare) = 0 Then
Set srg = sws.Range(srgAddress)
Set slCell = srg.Cells(sCellsCount) ' the same for all strings
For ss = ssLower To ssUpper
Set sfCell = srg.Find( _
What:=SearchStrings(ss), _
After:=slCell, _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows)
If Not sfCell Is Nothing Then ' string was found
FirstAddress = sfCell.Address ' to prevent an endless loop
Do
' Write to the Destination Worksheet.
dr = dr + 1
dws.Cells(dr, 3).Value = sfCell.Value
dws.Cells(dr, 2).Value = sfCell.Offset(-3, 0).Value
dws.Cells(dr, 1).Value = sfCell.Offset(-5, 0).Value
' Find next string.
Set sfCell = srg.FindNext(sfCell)
' Note that in this case, 'sfCell' will never ever
' be 'Nothing' once it's 'something'. The 'Find' method
' doesn't 'know' where it found the first: it just finds
' the next even if it's the same (it goes round and round)
' i.e. if there is one cell to find,
' it will find it 'forever'.
' That's the reason behind comparing with the first address.
Loop While sfCell.Address <> FirstAddress
Set sfCell = Nothing ' reset for the next string
'Else ' string was not found
End If
Next ss
End If
Next sws
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
'Inform: useful for short and long operations.
MsgBox "Retrieved price tag information.", vbInformation
End Sub
So it's working but it's pasting with 10 empty rows above and I am not sure why.
Sub Stuffff()
Dim Rng As Range
Set Rng = ThisWorkbook.Worksheets("Sheet2").Range("A1:AY300")
Rng.Copy
Dim s11 As Workbook
Set s11 = Workbooks("11 Production")
Dim last As Long
Dim Rngnew As Range
With s11.Sheets("Sheet1")
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
last = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
last = 1
End If
End With
Set Rngnew = s11.Worksheets("Sheet1").Range("A" & last + 1)
Rngnew.PasteSpecial
End Sub
Maybe you could try :
Sub Stuffff()
Dim Rng As Range
Set Rng = ThisWorkbook.Worksheets("Sheet2").Range("A1:AY300")
Rng.Copy
Dim s11 As Workbook
Set s11 = Workbooks("11 Production")
Dim last As Long
Dim Rngnew As Range
With s11.Sheets("Sheet1")
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
last = .range("A65000").end(xlup).offset(1,0).row
Else
last = 1
End If
End With
Set Rngnew = s11.Worksheets("Sheet1").Range("A" & last)
Rngnew.PasteSpecial
End Sub
That should work, unless you have more than 65 K rows in your workbook.
I work a cumulative report that grows daily up to about 150,000 rows of data. I am trying to run a macro that will move the data from one defined sheet to another defined sheet. Unfortunately, it is taking an extremely long time and leaves my Excel window frozen.
I have been staring at this code trying to make it work for our needs for so long that I haven't tried anything different.
Sub Move()
Application.ScreenUpdating = False
Dim Check As Range, r As Long, lastrow2 As Long, lastrow As Long
lastrow = Worksheets("From TaxWise").UsedRange.Rows.Count
lastrow2 = Worksheets("State").UsedRange.Rows.Count
If lastrow2 = 1 Then lastrow2 = 0
For r = lastrow To 2 Step -1
If Not Range("L" & r).Value = "US" Then
Rows(r).Cut Destination:=Worksheets("State").Range("A" & lastrow2 + 1)
lastrow2 = lastrow2 + 1
Else:
End If
Next r
On Error Resume Next
ActiveWorkbook.Worksheets("From TaxWise").Columns("C:C").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
Application.ScreenUpdating = True
End Sub
Not sure what I need to adjust as I feel my current code is running through 150,000 records line by line to identify, cut and move.
This code took about two seconds to run on 150000 records with about 3000 equal to US.
You'll need to alter it to match your setup. eg: Names of the various worksheets; cell ranges in case your tables don't start at A1, slightly different syntax if your data is in Excel Tables rather than just ranges, etc
It uses Excel's built-in autofilter
The destination sheet has all of the lines except for those with US.
Option Explicit
Sub noUS()
Dim wsSrc As Worksheet, wsDest As Worksheet
Dim rSrc As Range, rDest As Range
Const filterColumn As Long = 4 'Change to 12 for column L
Dim LRC() As Long
Set wsSrc = Worksheets("sheet1")
Set wsDest = Worksheets("sheet2")
Set rDest = wsDest.Cells(1, 1)
wsDest.Cells.Clear
With wsSrc
'get last row and column of the source worksheet
LRC = LastRowCol(.Name)
'set the range
Set rSrc = .Range(.Cells(1, 1), .Cells(LRC(0), LRC(1)))
'set the filter
'first turn it off
.AutoFilterMode = False
'now set it for the range
rSrc.AutoFilter _
field:=filterColumn, _
Criteria1:="<>US", _
visibledropdown:=False
End With
Set rSrc = rSrc.SpecialCells(xlCellTypeVisible)
rSrc.Copy rDest
'turn off the autofilter
wsSrc.AutoFilterMode = False
End Sub
'--------------------------------------------
Private Function LastRowCol(Worksht As String) As Long()
Application.Volatile
Dim WS As Worksheet, R As Range
Dim LastRow As Long, LastCol As Long
Dim L(1) As Long
Set WS = Worksheets(Worksht)
With WS
Set R = .Cells.Find(what:="*", after:=.Cells(1, 1), _
LookIn:=xlValues, searchorder:=xlByRows, _
searchdirection:=xlPrevious)
If Not R Is Nothing Then
LastRow = R.Row
LastCol = .Cells.Find(what:="*", after:=.Cells(1, 1), _
LookIn:=xlValues, searchorder:=xlByColumns, _
searchdirection:=xlPrevious).Column
Else
LastRow = 1
LastCol = 1
End If
End With
L(0) = LastRow
L(1) = LastCol
LastRowCol = L
End Function
And if you want to have a separate sheet with the US rows, you can insert the following before the end of the Sub:
'now get the US rows
With wsSrc
Set rSrc = .Range(.Cells(1, 1), .Cells(LRC(0), LRC(1)))
.AutoFilterMode = False
rSrc.AutoFilter _
field:=filterColumn, _
Criteria1:="US", _
visibledropdown:=False
Set rSrc = rSrc.SpecialCells(xlCellTypeVisible)
rSrc.Copy rUS
.AutoFilterMode = False
End With
I prefer to maintain the original data, rather than deleting stuff from the source. But, if you like, after you've done the above, and you are happy with the result, merely delete wsSrc
Edit
The above code modified so you wind up with, what I think you want, which is worksheets("State") containing all of the non-US items; and worksheets("From TaxWise") containing all of the US items.
Instead of deleting non-contiguous rows, a very slow process, we filter the rows we want to a new worksheet; delete the original worksheet, and rename the new sheet.
Don't try this at home without a backup of your original data.
Option Explicit
Sub noUS()
Dim wsSrc As Worksheet, wsDest As Worksheet, wsUS As Worksheet
Dim rSrc As Range, rDest As Range, rUS As Range
Const filterColumn As Long = 12
Dim LRC() As Long
Set wsSrc = Worksheets("From TaxWise")
Set wsDest = Worksheets("State")
Set rDest = wsDest.Cells(1, 1)
wsDest.Cells.Clear
With wsSrc
'get last row and column of the source worksheet
LRC = LastRowCol(.Name)
'set the range
Set rSrc = .Range(.Cells(1, 1), .Cells(LRC(0), LRC(1)))
'set the filter
'first turn it off
.AutoFilterMode = False
'now set it for the range
rSrc.AutoFilter _
field:=filterColumn, _
Criteria1:="<>US", _
visibledropdown:=False
End With
Set rSrc = rSrc.SpecialCells(xlCellTypeVisible)
rSrc.Copy rDest
'turn off the autofilter
wsSrc.AutoFilterMode = False
'now get the US rows, may need to add worksheet
On Error Resume Next
Set wsUS = Worksheets("US")
If Err.Number = 9 Then
Worksheets.Add
ActiveSheet.Name = "US"
End If
Set wsUS = Worksheets("US")
Set rUS = wsUS.Cells(1, 1)
With wsSrc
Set rSrc = .Range(.Cells(1, 1), .Cells(LRC(0), LRC(1)))
.AutoFilterMode = False
rSrc.AutoFilter _
field:=filterColumn, _
Criteria1:="US", _
visibledropdown:=False
Set rSrc = rSrc.SpecialCells(xlCellTypeVisible)
rSrc.Copy rUS
.AutoFilterMode = False
End With
'Delete Taxwise and rename US sheets
Application.DisplayAlerts = False
wsSrc.Delete
wsUS.Name = "From TaxWise"
Application.DisplayAlerts = True
End Sub
'--------------------------------------------
Private Function LastRowCol(Worksht As String) As Long()
Application.Volatile
Dim WS As Worksheet, R As Range
Dim LastRow As Long, LastCol As Long
Dim L(1) As Long
Set WS = Worksheets(Worksht)
With WS
Set R = .Cells.Find(what:="*", after:=.Cells(1, 1), _
LookIn:=xlValues, searchorder:=xlByRows, _
searchdirection:=xlPrevious)
If Not R Is Nothing Then
LastRow = R.Row
LastCol = .Cells.Find(what:="*", after:=.Cells(1, 1), _
LookIn:=xlValues, searchorder:=xlByColumns, _
searchdirection:=xlPrevious).Column
Else
LastRow = 1
LastCol = 1
End If
End With
L(0) = LastRow
L(1) = LastCol
LastRowCol = L
End Function
You can filter and work with visible cells or you can avoid deleting rows inside your loop.
Say, for instance, that you have 500 cells that are not equal to US. You will then have 500 instances of copy/paste & deletions. This is highly inneficient.
Instead, add your target cells to a Union (collection of cells) and then outside of the loop, perform your operations on the collection. No matter how many rows are being targeted, you will have just one instance of copy, one instance of paste, and one instance of deletion.
Sub Moving()
Dim cs As Worksheet: Set cs = ThisWorkbook.Sheets("From TaxWise")
Dim ps As Worksheet: Set ps = ThisWorkbook.Sheets("State")
Dim MoveMe As Range, myCell As Range, LR2 As Long
Dim LR As Long: LR = cs.Range("L" & cs.Rows.Count).End(xlUp).Row
For Each myCell In cs.Range("L2:L" & LR)
If myCell <> "US" Then
If Not MoveMe Is Nothing Then
Set MoveMe = Union(MoveMe, myCell)
Else
Set MoveMe = myCell
End If
End If
Next myCell
If Not MoveMe Is Nothing Then
LR2 = ps.Range("A" & ps.Rows.Count).End(xlUp).Row
MoveMe.EntireRow.Copy
ps.Range("A" & LR2).PasteSpecial xlPasteValues
MoveMe.EntireRow.Delete
End If
End Sub
Move Rows
Union Version
Option Explicit
Sub Move()
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
End With
Dim rngU As Range, r As Long, lastrow2 As Long, lastrow As Long
On Error GoTo ProcedureExit
With Worksheets("From Taxwise")
lastrow = .Cells(.Rows.Count, "L").End(xlUp).row
For r = 2 To lastrow
If Not .Range("L" & r).Value = "US" Then
If Not rngU Is Nothing Then
Set rngU = Union(rngU, .Cells(r, 1))
Else
Set rngU = .Cells(r, 1)
End If
End If
Next
End With
If Not rngU Is Nothing Then
With Worksheets("State")
lastrow2 = .Cells(.Rows.Count, "L").End(xlUp).row
rngU.EntireRow.Copy .Range("A" & lastrow2 + 1)
rngU.EntireRow.Delete
End With
Set rngU = Nothing
End If
ProcedureExit:
With Application
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
I have written the following code which should, match column headings in destination workbook, search for the same column heading in the source workbook (worksheet), fetch all the data under that particular column till the end of the row and copy it under the same column heading in the destination workbook (worksheet).
This task should be performed till all the columns in the destination workbook's worksheet gets filled.
Sub LPN()
Dim CurrentWS As Worksheet
Set CurrentWS = ActiveSheet
ActiveWorkbook.Sheets("controls").Select
'I have made a sheet in the main workbook(Rates EMEA CDS PT+FVA.v1.25 Apr 2016.i1.xlsm)
' known as **controls** , in this sheet I have specified the path of the
' workbook(worksheet) that has to be opened and from where the data has to be copied.
'The name of the cell where the path has been mentioned I named it as GPL
Set master = ActiveWorkbook
GPL = Range("GPL").Value
Workbooks.Open Filename:=GPL
Set GPLfile = ActiveWorkbook
'Open the particular workbook with specified worksheet having .xlsx extension
Dim SourceWS As Worksheet
Set SourceWS = ActiveWorkbook.Worksheets("PNL Attribution")
Dim SourceHeaderRow As Integer: SourceHeaderRow = 1
Dim SourceCell As Range
Workbooks("Rates EMEA CDS PT+FVA.v1.25 Apr 2016.i1.xlsm").Activate
Dim TargetWS As Worksheet
Set TargetWS = Worksheets("PNL Attribution")
Dim TargetHeader As Range
'The code will look for all the column headings in the source workbook
' match it with the headings in the target workbook(worksheet) which are not in order.
Set TargetHeader = TargetWS.Range("A10:ZZ10")
Dim RealLastRow As Long
Dim SourceCol As Integer
SourceWS.Activate
For Each Cell In TargetHeader
If Cell.Value <> "" Then
Set SourceCell = Rows(SourceHeaderRow).Find _
(Cell.Value, LookIn:=xlValues, LookAt:=xlWhole)
If Not SourceCell Is Nothing Then
SourceCol = SourceCell.Column
RealLastRow = Columns(SourceCol).Find("*", LookIn:=xlValues, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
If RealLastRow > SourceHeaderRow Then
Range(Cells(SourceHeaderRow + 1, SourceCol), Cells(RealLastRow, _
SourceCol)).copy
TargetWS.Cells(2, Cell.Column).PasteSpecial xlPasteValues
End If
End If
End If
Next
CurrentWS.Activate
End Sub
Can you adapt it to your task?
Sub Cols_Value_Add_test()
Set shSour = Worksheets("1")
Set shDest = Worksheets("2")
Dim rngSour As Range, rngDest As Range
Set rngSour = shSour.Cells(3, 2)
Set rngDest = shDest.Cells(3, 3)
Dest_Row = rngDest.Row + rngDest.CurrentRegion.Rows.Count
Cols_Value_Add rngSour, rngDest
End Sub
Sub Cols_Value_Add(rngSour As Range, _
rngDest As Range)
Dim rngDest_Col As Long, rngDest_Col_Max As Long
Dim shSour_Col As Long
rngDest_Col_Max = rngDest.CurrentRegion.Columns.Count
For rngDest_Col = 1 To rngDest_Col_Max
shSour_Col = shSour_Col_Find(rngDest, rngDest_Col)
If shSour_Col > 0 Then _
CopyPaste rngSour, shSour_Col, rngDest, rngDest_Col
Next
End Sub
Sub CopyPaste(rngSour As Range, _
shSour_Col As Long, _
rngDest As Range, _
rngDest_Col As Long)
Dim Sour_Row_Max As Long
Sour_Row_Max = rngSour.CurrentRegion.Row + rngSour.CurrentRegion.Rows.Count - 1
With shSour
Set rngSour = .Range(.Cells(rngSour.Row, shSour_Col), _
.Cells(Sour_Row_Max, shSour_Col))
End With
rngSour.Copy
rngDest_Col = rngDest.Row + rngDest_Col - 1
shDest.Cells(Dest_Row, rngDest_Col).PasteSpecial _
Paste:=xlPasteValues
End Sub
Function shSour_Col_Find(rngDest As Range, _
rngDest_Col As Long) _
As Long
Dim sHeader As String, rng As Range
sHeader = rngDest.Cells(1, rngDest_Col).Value
Set rng = shSour.Cells.Find(sHeader, , , xlWhole)
If Not rng Is Nothing Then _
shSour_Col_Find = rng.Column
End Function