I have a macro with this loop which take a lot of time :
Dim tempval As String
Dim row As Integer, col As Integer
Application.ScreenUpdating = False
For row = 2 To 500 Step 1
tempval = ""
For col = 7 To 15 Step 1
tempval = tempval & Cells(row, col).Value
Cells(row, col).Value = ""
Next col
Cells(row, 7).Value = tempval
For col = 8 To 16 Step 1
tempval = tempval & Cells(row, col).Value
Cells(row, col).Value = ""
Next col
Cells(row, 8).Value = tempval
Next row
Application.ScreenUpdating = True
Range("LibAnglais2:LibAnglais9").Select
Selection.Delete Shift:=xlToLeft
Range("LibFrancais2:LibFrancais9").Select
Selection.Delete Shift:=xlToLeft
There is code, before, and after this loop.
With this loop, the code takes 3 minutes to end. Without, it takes 30s.
But when I click on the excel windows during the loop (You know when a program run, you click, the window become a white blur screen), my macro finish after I clicked and take approximately 45s...
Do you have an idea why ? And how can fix this to have a faster macro ?
Work with a variant array loaded in bulk directly from the worksheet. Use the Join Function for your concatenation (Chr(124) is the 'pipe' character) and return the processed values back to the worksheet en masse.
Option Explicit
Sub sonic()
Dim r As Long, vTMPs() As Variant, vVALs() As Variant
Application.ScreenUpdating = False
Application.EnableEvents = True
Application.Calculation = xlCalculationManual
With Worksheets("Sheet1")
vTMPs = .Range("G2:P500").Value2
ReDim vVALs(LBound(vTMPs, 1) To UBound(vTMPs, 1), LBound(vTMPs, 2) To 2)
For r = LBound(vVALs, 1) To UBound(vVALs, 1)
vVALs(r, 1) = Join(Array(vTMPs(r, 1), vTMPs(r, 2), vTMPs(r, 3), vTMPs(r, 4), _
vTMPs(r, 5), vTMPs(r, 6), vTMPs(r, 7), vTMPs(r, 8)), Chr(124))
vVALs(r, 2) = Join(Array(vTMPs(r, 2), vTMPs(r, 3), vTMPs(r, 4), vTMPs(r, 5), _
vTMPs(r, 6), vTMPs(r, 7), vTMPs(r, 8), vTMPs(r, 9)), Chr(124))
Next r
.Range("G2:P500").ClearContents
.Range("G2").Resize(UBound(vVALs, 1), UBound(vVALs, 2)) = vVALs
Application.ScreenUpdating = True
'I don't know what the following is supposed to do
.Range("LibAnglais2:LibAnglais9").Delete Shift:=xlToLeft
.Range("LibFrancais2:LibFrancais9").Delete Shift:=xlToLeft
End With
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
End Sub
Sometimes VBA needs to process messages to be faster. I don't really know why but if some of my macros act up like that I add a DoEvents line in the loop before the Next and it does wonders. It is not recommended for more complex applications. Here you can find a description of it: https://support.office.com/en-us/article/DoEvents-Function-7af41eca-88e0-470d-adaf-0b3d4c2575b0
So your code would be:
DoEvents
Next row
HTH
Ok guys, so, I found the solution.
In fact, I had a other sub in my code :
Private Sub Worksheet_Change(ByVal Target As Range)
And the code pass on this sub each time a cell was modified.
So I put a :
Application.EnableEvents = False
On my code, and it's work !
Thank's for your help !
EDIT : In fact, the problem is not totally solved... I noticed that the code take a lot of time after saving the worksheet or simply after modifiying the code... Do you have a solution ?
Related
I have a dataset that I paste just below a table in which it extends to include it. I then combine all duplicate rows. However, I added two additional columns to the table that i would like to have notes in. However, when I later combine the duplicate rows, the newer row's blank cells overwrite any notes I had in there. Columns AC and AD are my notes cells. I have been trying to use a concatenate method to get around it overwriting it, however I found this awesome macro to combine duplicates but I cant for the life of me figure out how to write a line that would not delete my notes columns in the combine process! Any help would be greatly appreciated!!
Option Explicit
Sub removeDupesKeepLast()
Dim d As Long, dDQs As Object, ky As Variant
Dim r As Long, c As Long, vVALs As Variant, vTMP As Variant
'appTGGL bTGGL:=False 'uncomment this when you have finished debugging
Set dDQs = CreateObject("Scripting.Dictionary")
dDQs.comparemode = vbTextCompare
'step 1 - bulk load the values
With Worksheets("Master RFL Pipeline").Range("Table135") 'you should know what worksheet you are on
With .Cells(1, 1).CurrentRegion 'block of data radiating out from A1
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0) 'step off the header row
vVALs = .Value 'use .Value2 if you do not have dates in unformatted cells
End With
End With
End With
'step 2 - build the dictionary
ReDim vTMP(UBound(vVALs, 2) - 1)
For r = LBound(vVALs, 1) To UBound(vVALs, 1)
For c = LBound(vVALs, 2) To UBound(vVALs, 2)
vTMP(c - 1) = vVALs(r, c)
Next c
dDQs.Item(vVALs(r, 1) & ChrW(8203)) = vTMP
Next r
'step 3 - put the de-duplicated values back into the array
r = 0
ReDim vVALs(1 To dDQs.Count, LBound(vVALs, 2) To UBound(vVALs, 2))
For Each ky In dDQs
r = r + 1
vTMP = dDQs.Item(ky)
For c = LBound(vTMP) To UBound(vTMP)
vVALs(r, c + 1) = vTMP(c)
Next c
Next ky
'step 4 - clear the destination; put the de-duplicated values back into the worksheet and reset .UsedRange
With Worksheets("Master RFL Pipeline").Range("Table135") 'you should know what worksheet you are on
With .Cells(1, 1).CurrentRegion 'block of data radiating out from A1
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0) 'step off the header row
.ClearContents 'retain formatting if it is there
.Cells(1, 1).Resize(UBound(vVALs, 1), UBound(vVALs, 2)) = vVALs
End With
End With
.UsedRange 'assert the UsedRange property (refreshes it)
End With
dDQs.RemoveAll: Set dDQs = Nothing
appTGGL
End Sub
Public Sub appTGGL(Optional bTGGL As Boolean = True)
With Application
.ScreenUpdating = bTGGL
.EnableEvents = bTGGL
.DisplayAlerts = bTGGL
.AutoRecover.Enabled = bTGGL 'no interruptions with an auto-save
.Calculation = IIf(bTGGL, xlCalculationAutomatic, xlCalculationManual)
.CutCopyMode = False
.StatusBar = vbNullString
End With
Debug.Print Timer
End Sub
I need to create a sub to consolidate some data. I have several rows (anywhere from 4k to 20k) that I need to consolidate and sum the values from each column (from C to N).
The input data looks like this:
input
For the output, it should sum the columns for each SKU (Column A) and delete the rest.
Like this:
output
It should be simple enough, but I can’t seem to come up with an appropriate solution. I tried using an array with a scripting dictionary but I can’t figure out how to store more than a single value for each key. Sample (unfinished) code:
Dim sArray As Variant
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
sArray = Range(currentRange).Value
For i = 1 To UBound(sArray, 1)
For j = 3 To UBound(sArray, 2)
If dict.exists(sArray(i, 1)) = False Then
dict.Add sArray(i, 1), sArray(i, j)
Else
'this part is very wrong:
dict(sArray(i, 1)) = dict(sArray(i, j)) + sArray(i, j)
End If
Next
Next
Thank you very much in advance!
Try this, It sums the values in Column Q:AB then paste them back and removes the duplicates.
Sub dupremove()
Dim ws As Worksheet
Dim lastrow As Long
Set ws = Sheets("Sheet12") ' Change to your sheet
With ws
lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
With .Range("C2:N" & lastrow)
.Offset(, 14).FormulaR1C1 = "=SUMIF(C1,RC1,C[-14])"
.Value = .Offset(, 14).Value
.Offset(, 14).ClearContents
End With
With .Range("A1:N" & lastrow)
.Value = .Value
.RemoveDuplicates 1, xlYes
End With
End With
Before:
After:
I came up with the following solution instead and it took 30 seconds to run it (not entirely my own idea, borrowed some code from someplace else):
Sub dupes()
Dim MyRange As Range
Dim RowNum As Long
RowNum = 1
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set MyRange = Range("A2:N14200") 'for test only, on the real sub it's dynamic
MyRange.Sort key1:=Range("A2"), order1:=xlAscending
For Each Row In MyRange
With Cells
While Cells(RowNum, 1) = Cells(RowNum + 1, 1) And Cells(RowNum + 1, 1) <> "" 'very important the second condition or it will continue to loop forever
For i = 3 To 14
Cells(RowNum, i) = Cells(RowNum, i) + Cells(RowNum + 1, i)
Next
Rows(RowNum + 1).EntireRow.Delete
Wend
End With
RowNum = RowNum + 1
Next
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
It's kinda messy but it does the trick. Thanks to everyone!
I prefer to use the function .value, because i dont miss anything, but i cant to paste or the all range
Anyone know how i can do?
Sub AUTO()
Application.ScreenUpdating = False
'sheet that i want paste
PasteData1 = ActiveSheet.Cells(3, 6).Value
DATAAUTO = "L:\ANALISTA_M\Frade\FINANCIAL SERVICES\INSURANCE\Mercado\SUSEP\Planilhas\Auto-Susep.xlsx"
Workbooks.Open (DATAAUTO)
sName = ActiveSheet.Name
'count the number of rows and columns
i = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row - 11
c = ActiveSheet.Cells(6, Columns.Count).End(xlToLeft).Column
'select all range that i want
COPYDATE = ActiveSheet.Range(Cells(6, 1), Cells(i, c)).Value
PASTEAUTO = "L:\ANALISTA_M\Frade\FINANCIAL SERVICES\INSURANCE\Mercado\SUSEP\Auto.xlsm"
Workbooks.Open (PASTEAUTO)
Worksheets(PasteData1).Activate
'the problem is here!!! i need to respect a order the beging my paste
ActiveSheet.Cells(2, 2).Value = COPYDATE
ActiveSheet.Range(Cells(2, 2), Cells(i - 4, c + 1)).Replace What:=".", Replacement:=""
ActiveSheet.Range(Cells(2, 2), Cells(i - 4, c + 1)).Replace What:=",", Replacement:="."
Worksheets("Consolidado").Activate
Workbooks("Auto-Susep.xlsx").Close
Application.ScreenUpdating = True
End Sub
to use the .Value over copy paste you need to have the same size range. You have one cell trying to hold a 2 dimensional array.
So change:
ActiveSheet.Cells(2, 2).Value = COPYDATE
to:
ActiveSheet.Cells(2, 2).Resize(UBound(COPYDATE,1),UBound(COPYDATE,2)).Value = COPYDATE
Also I do not see where you declare any of your variables, that is a bad habit, one should always declare their variables even if they are of a Variant type.
Dim COPYDATE() as Variant
I have a very large data set (600,000 rows) of data structured in the following format:
1) There are around 60 products. One is a Total US number, while the others are for Manufacturers and are labled as KMFs. There are also some labeled as PCKGs(but aren't relevant for this question)
2) Each product is located in 60 different markets
3) Each market has 20 different locations
4) I have 12 metrics for which I need to calculate data in the following manner: Total US number - sum(KMFs) for each metric
I have written vba code for this but it is taking too long to run(around 20 minutes) I need to run similar code on at least 20 worksheets. I have tried various methods such as setting screenUpdating etc. to false. Here is my code. I am new to vba coding so I may have missed obvious things. Please let me know anything is unclear. Please help!
Sub beforeRunningCode()
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
ActiveSheet.DisplayPageBreaks = False
End Sub
Sub returnToOriginal()
Application.ScreenUpdating = screenUpdateState
Application.DisplayStatusBar = statusBarState
Application.Calculation = calcState
Application.EnableEvents = eventsState
ActiveSheet.DisplayPageBreaks = displayPageBreaksState
End Sub
Function LastRowFunc(Sheet) As Long
LastRowFunc = ActiveWorkbook.Worksheets(Sheet).Range("A2", Worksheets(Sheet).Range("A2").End(xlDown)).Rows.Count
End Function
Function LastColFunc(Sheet) As Long
With ActiveSheet
LastColFunc = ActiveWorkbook.Sheets(Sheet).Cells(1, .Columns.Count).End(xlToLeft).Column
End With
End Function
Sub AOCalculate()
Call beforeRunningCode 'Optimize Excel
Dim LastRow As Long
Dim LastCol As Long
Dim Period As String
Dim Sheet As String
Dim Arr(1 To 16)
Dim Count As Integer
Sheet = "Energy_LS_Bottler"
Period = "2016 WAVE 1 - 3 W/E 05/07"
LastRow = LastRowFunc(Sheet) 'Calculate last row for which data exists
LastCol = LastColFunc(Sheet) 'Calculate last column for which data exists
For Each Location In ActiveWorkbook.Sheets("Locations").Range("D7:D28").Value
For Each Market In ActiveWorkbook.Sheets("Markets").Range("A5:A92").Value
Count = Count + 1
Arr(1) = Market
Arr(2) = "AO"
Arr(3) = Location
Arr(4) = Period
With ActiveWorkbook.Sheets(Sheet) 'Filtering for KMF
.AutoFilterMode = False
.Range(Cells(1, 1), Cells(LastRow, LastCol)).AutoFilter
.Range(Cells(1, 1), Cells(LastRow, LastCol)).AutoFilter field:=17, Criteria1:="=KMF"
.Range(Cells(1, 1), Cells(LastRow, LastCol)).AutoFilter field:=1, Criteria1:=Market
.Range(Cells(1, 1), Cells(LastRow, LastCol)).AutoFilter field:=3, Criteria1:=Location
End With
For k = 5 To 16
Arr(k) = Application.WorksheetFunction.Sum(ActiveWorkbook.Sheets(Sheet).Range(Cells(1, k), Cells(LastRow, k)).SpecialCells(xlCellTypeVisible))
Next k
With ActiveWorkbook.Sheets(Sheet) ' filtering for Total US
.AutoFilterMode = False
.Range(Cells(1, 1), Cells(LastRow, LastCol)).AutoFilter
.Range(Cells(1, 1), Cells(LastRow, LastCol)).AutoFilter field:=17, Criteria1:="=Total US"
.Range(Cells(1, 1), Cells(LastRow, LastCol)).AutoFilter field:=1, Criteria1:=Market
.Range(Cells(1, 1), Cells(LastRow, LastCol)).AutoFilter field:=3, Criteria1:=Location
End With
For k = 5 To 16
Arr(k) = -Arr(k) + Application.WorksheetFunction.Sum(ActiveWorkbook.Sheets(Sheet).Range(Cells(1, k), Cells(LastRow, k)).SpecialCells(xlCellTypeVisible))
Next k
For j = 1 To 16
ActiveWorkbook.Sheets(Sheet).Cells(LastRow + Count, j).Value = Arr(j)
Next j
Erase Arr
Next
Next
ActiveWorkbook.Sheets(Sheet).AutoFilterMode = False
Call returnToOriginal
End Sub
[Edit]: Here is a link to a sample data set https://drive.google.com/file/d/0B3MkGa57h6g_WGl2WWlWekd4NU0/view?usp=sharing
I think that this will work (though I haven't had a chance to test it), and should be a lot faster:
Sub AOCalculate()
Call beforeRunningCode 'Optimize Excel
Dim LastRow As Long
Dim LastCol As Long
Dim Period As String
Dim Sheet As String
Dim Arr() '1 To 2000, 1 To 16)
Dim Count As Integer
Sheet = "Energy_LS_Bottler"
Period = "2016 WAVE 1 - 3 W/E 05/07"
LastRow = LastRowFunc(Sheet) 'Calculate last row for which data exists
LastCol = LastColFunc(Sheet) 'Calculate last column for which data exists
'copy all of the relevant cells to local arrays for speed
Dim Locations(), Markets(), data()
Markets = ActiveWorkbook.Sheets("Markets").Range("A5:A92").Value
Locations = ActiveWorkbook.Sheets("Locations").Range("D7:D28").Value
'(pretty sure the following line needs to localize the Cells() to .Cells())
data = ActiveWorkbook.Sheets(Sheet).Range(Cells(1, 1), Cells(LastRow, LastCol)).Value '**'
ReDim Arr(1 To UBound(Markets, 1) * UBound(Locations, 1), 16)
'make an index of pointers into our accumulation array
Dim counts As New Collection
Dim i As Long, l As Long, m As Long
For l = 1 To UBound(Locations, 1)
Location = Locations(l, 1) '**'
For m = 1 To UBound(Markets, 1)
Market = Markets(m, 1) '**'
i = i + 1
counts.Add i, CStr(Location) & "~" & CStr(Market)
'counts.Add NewAccumArray(Location, Market, Period), CStr(Location) & "~" & CStr(Market)
Arr(i, 1) = Market
Arr(i, 2) = "AO"
Arr(i, 3) = Location
Arr(i, 4) = Period
Next
Next
' go through each row and add it to the appropiate count in the array
Dim r As Long
Dim key As String, idx As Long
For r = 1 To UBound(data, 1)
key = CStr(data(r, 3)) & "~" & CStr(data(r, 1))
If data(r, 17) = "KMF" Then
idx = counts(key)
For k = 5 To 16
Arr(idx, k) = Arr(idx, k) - data(r, k)
Next k
Else
If data(r, 17) = "Total US" Then
idx = counts(key)
For k = 5 To 16
Arr(idx, k) = Arr(idx, k) + data(r, k)
Next k
End If
End If
Next r
' output the results
ActiveWorkbook.Sheets(Sheet).Range(Cells(LastRow + 1, 1), Cells(LastRow + Count, 16)).Value = Arr
ActiveWorkbook.Sheets(Sheet).AutoFilterMode = False
Call returnToOriginal
End Sub
Answering the query "What did I mean by this?"
'(pretty sure the following line needs to localize the Cells() to .Cells())
data = ActiveWorkbook.Sheets(Sheet).Range(Cells(1, 1), Cells(LastRow, LastCol)).Value '**'
The use of Cells(..) here is fundamentally unreliable and broken. this is because Cells(..) is really a shortcut for ActiveSheet.Cells(..) and the Active* properties are inherently slow and unreliable because they can change while the code is running. Worse, this code is assuming that ActiveSheet = Energy_LS_Blotter which is far from certain.
The correct way to write this line would be like this:
data = ActiveWorkbook.Sheets(Sheet).Range( _
ActiveWorkbook.Sheets(Sheet).Cells(1, 1), _
ActiveWorkbook.Sheets(Sheet).Cells(LastRow, LastCol) _
).Value
But that is long, ugly and inconvenient. An easier way would be to use either a Sheet variable, or a With:
With ActiveWorkbook.Sheets(Sheet)
data = .Range(.Cells(1, 1), .Cells(LastRow, LastCol)).Value
End With
I have a macro that will take each value in a list, place it in a different sheet (which performs its own calculations) and returns certain values (like a summary sheet). I have created a looping macro to do this very action, but since there are about 6500 entries on the list, the macro executes at a very slow pace. I have turned off screen updating, and calculations have to be automatic, so I was wondering: is there any other way to speed up the macro?
Sub watchlist_updated()
Application.ScreenUpdating = False
Range("A10").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.ClearContents
Range("B10:Q10").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.ClearContents
Sheets("Analysis").Select
Range("C5:D5").ClearContents
Range("N6").Select
ActiveCell.FormulaR1C1 = "Yes"
Sheets("Selected Data").Select
Range("C6").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("Watchlist").Select
Range("A10").Select
ActiveSheet.Paste
countermax = Selection.Count
Range("A10").Select
counter = 1
Do Until ActiveCell = ""
sStatus = Format(counter / countermax, "0.0%") & " Complete"
Application.StatusBar = sStatus
Sheets("Analysis").Range("C5") = ActiveCell.Value
Dim array1(16)
Dim myrange As Range
Set myrange = Range(ActiveCell.Offset(0, 1), ActiveCell.Offset(0, 16))
array1(0) = Sheets("Analysis").Range("F5").Value
array1(1) = Sheets("Analysis").Range("C20").Value
array1(2) = Sheets("Analysis").Range("J2").Value
array1(3) = Sheets("Analysis").Range("B8").Value
array1(4) = Sheets("Analysis").Range("J13").Value
array1(5) = Sheets("Analysis").Range("R13").Value
array1(6) = Sheets("Analysis").Range("C21").Value
array1(7) = Sheets("Analysis").Range("B11").Value
array1(8) = Sheets("Analysis").Range("V5").Value
array1(9) = Sheets("Analysis").Range("B12").Value
array1(10) = Sheets("Analysis").Range("J6").Value
array1(11) = Sheets("Analysis").Range("B9").Value
array1(12) = Sheets("Analysis").Range("N20").Value
array1(13) = Sheets("Analysis").Range("H23").Value
array1(14) = Sheets("Analysis").Range("F23").Value
array1(15) = Sheets("Analysis").Range("D23").Value
myrange = array1
ActiveCell.Offset(1, 0).Select
counter = counter + 1
Loop
Application.StatusBar = False
Sheets("Analysis").Select
Range("N6").Select
ActiveCell.FormulaR1C1 = "No"
Sheets("Watchlist").Select
Application.ScreenUpdating = True
Application.StatusBar = False
End Sub
The key to speedy VBA loop is to minimise interaction with the workbook inside the loop.
In your case you won't be able to eliminate interaction entirely, but you can reduce it substantially.
Key steps are:
You can use Manual calculation. (see below)
Create Worksheet and Range objects variables to refer to your sheets and ranges
Create Variant Array's to hold your source data, result data and Analysis results
Once you have a reference to your source data, copy it into a Variant Array. do a For loop over the rows of this array (rather than using ActiveCell)
Create a Results array, sized to the source data rows, by 16 columns wide
On each iteration, copy the source data value onto the Analysis sheet (here's where you can't avoid some workbook interaction)
Force a recalculation of the Analysis sheet with wsAnalysis.Calculate
Copy the results to a variant array in one step. I'd copy the range A1:V23. (Copying too many cells in one step is faster than copying many cells one at a time)
Map the required results into your Results array, into the current row
After the loop, copy the result array to the results range in your workbook (again in one step)
Other notes:
Eliminate all the Select, Selection, ActiveSheet, ActiveCell stuff (as others have mentioned)
Declare all your variables
Be explicit of Lower and Upper bounds in your array declarations
Provide an Error Handler, and CleanUp code to turn on Application properties even when the code errors
After all this, performance will depend on the calculation time of your Analysis worksheet. There may be opportunity for improvement there too, if you would care to share its details
Whilst this won't speed up the entire thing. You can defs save on time by getting rid of the 'select/selection' bits.
For example for that first section replace:
Range("A10").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.ClearContents
with:
Range([A10],[A10].End(xlDown)).ClearContents
Note: the use of [] in this case replaces Range(). Not always healthy to use this shortcut but for your purposes it should be fine.
You should always try and rewrite a code you recorded with this formatting before anything else, it bypasses the clumsiness of the macro recorder and turns it into neat vba code :)
It is not very pretty but it is fast. I am not very good with making Array's faster but this could be an alternative solution.
Sub watchlist_updated()
'***Define your Variables***
Dim wsAnalysis As Excel.Worksheet
Dim wsWatchList As Excel.Worksheet
Dim wsSelectData As Excel.Worksheet
Dim LastRow1 As Long
Dim LastRow2 As Long
Dim LastRow3 As Long
'***Set the objects***
Set wsAnalysis = Sheets("Analysis")
Set wsWatchList = Sheets("Watchlist")
Set wsSelectData = Sheets("Selected Data")
'***Turn off Background***
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
'***Finding Last Row - Each Sheet***
LastRow1 = wsSelectData.Range("C" & Rows.Count).End(xlUp).Row
LastRow2 = wsAnalysis.Range("A" & Rows.Count).End(xlUp).Row
LastRow3 = wsWatchList.Range("C" & Rows.Count).End(xlUp).Row
'***Handle any Errors***
On Error GoTo ErrorHandler:
With wsWatchList
.Range(.Cells(10, 1), .Cells(10 + LastRow3, 17)).ClearContents
End With
With wsAnalysis
.Range("C5:D5").ClearContents
.Range("N6").FormulaR1C1 = "Yes"
End With
'***New Copy & Paste Method***
wsWatchList.Range(wsWatchList.Cells(10, 1), wsWatchList.Cells(10 + LastRow1, 1)).Value = _
wsSelectData.Range(wsSelectData.Cells(6, 3), wsSelectData.Cells(6 + LastRow1, 3)).Value
wsAnalysis.Range("C5") = LastRow1 - 5
wsWatchList.Range(wsWatchList.Cells(10, 2), wsWatchList.Cells(LastRow1 + 4, 2)).Value = wsAnalysis.Range("F5").Value
wsWatchList.Range(wsWatchList.Cells(10, 3), wsWatchList.Cells(LastRow1 + 4, 3)).Value = wsAnalysis.Range("C20").Value
wsWatchList.Range(wsWatchList.Cells(10, 4), wsWatchList.Cells(LastRow1 + 4, 4)).Value = wsAnalysis.Range("J2").Value
wsWatchList.Range(wsWatchList.Cells(10, 5), wsWatchList.Cells(LastRow1 + 4, 5)).Value = wsAnalysis.Range("B8").Value
wsWatchList.Range(wsWatchList.Cells(10, 6), wsWatchList.Cells(LastRow1 + 4, 6)).Value = wsAnalysis.Range("J13").Value
wsWatchList.Range(wsWatchList.Cells(10, 7), wsWatchList.Cells(LastRow1 + 4, 7)).Value = wsAnalysis.Range("C21").Value
wsWatchList.Range(wsWatchList.Cells(10, 8), wsWatchList.Cells(LastRow1 + 4, 8)).Value = wsAnalysis.Range("B11").Value
wsWatchList.Range(wsWatchList.Cells(10, 9), wsWatchList.Cells(LastRow1 + 4, 9)).Value = wsAnalysis.Range("V5").Value
wsWatchList.Range(wsWatchList.Cells(10, 10), wsWatchList.Cells(LastRow1 + 4, 10)).Value = wsAnalysis.Range("B12").Value
wsWatchList.Range(wsWatchList.Cells(10, 11), wsWatchList.Cells(LastRow1 + 4, 11)).Value = wsAnalysis.Range("J6").Value
wsWatchList.Range(wsWatchList.Cells(10, 12), wsWatchList.Cells(LastRow1 + 4, 12)).Value = wsAnalysis.Range("B9").Value
wsWatchList.Range(wsWatchList.Cells(10, 13), wsWatchList.Cells(LastRow1 + 4, 13)).Value = wsAnalysis.Range("N20").Value
wsWatchList.Range(wsWatchList.Cells(10, 14), wsWatchList.Cells(LastRow1 + 4, 14)).Value = wsAnalysis.Range("H23").Value
wsWatchList.Range(wsWatchList.Cells(10, 15), wsWatchList.Cells(LastRow1 + 4, 15)).Value = wsAnalysis.Range("F23").Value
wsWatchList.Range(wsWatchList.Cells(10, 16), wsWatchList.Cells(LastRow1 + 4, 16)).Value = wsAnalysis.Range("D23").Value
wsAnalysis.Range("N6").FormulaR1C1 = "No"
wsWatchList.Select
'***Clean Up***
BeforeExit:
Set wsAnalysis = Nothing
Set wsWatchList = Nothing
Set wsSelectData = Nothing
'***Turn on Background***
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
Exit Sub
'***Add in a simple ErrorHandler***
ErrorHandler:
MsgBox "Error"
GoTo BeforeExit
End Sub
Hope this helps!