Optimizing VBA copy/paste functions and loops - vba

I have a large Excel sheet. I'm interested in moving data from one cell to another. I have researched on how to optimize the copy/paste function to take as little time as possible and found that:
Sheet1.Range("A1").Value = Sheet1.Range("B1").Value
or
Sheet1.Range("A1").Copy Destination:=Sheet1.Range("B1")
is faster than:
Sheet1.Range("A1").Copy
Sheet1.Range("A1").PasteSpecial xlPasteValues
Application.CutCopyMode=False'Clear Clipboard
Now, I need to make a copy with the following options:
Range("A1").Select
Selection.Copy
Range("B1").Select
Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=False
Is it possible to translate that into the code similar to one of the previous mentioned?
Also, in regard to loops. Is it generally faster to avoid them (if possible) or how is the Compiler optimized? Let me give you an example so you don't misunderstand me:
Lets say I want to Copy values from "A1:A200" to "B1:B200". Which method would then be better in general?
Dim counter As Integer
For counter = 1 To 200
Sheet1.Range("A" & CStr(counter)) = Sheet1.Range("B" & CStr(counter))
End counter
Or is it better to simply use the code:
Sheet1.Range("A1:A200").Copy Destination:=Sheet1.Range("B1:200")
These examples are of cause grossly simplified, though if someone could help me understand the principles applied, it would be of great value to me!

First of all don't use Select and Selection. This really slows your code. Especially in loops.
The fastest way to copy values is to simply do this Range("B1:B99").Value=Range("A1:A99").Value
Furthermore you should deactivate Screenupdating and especially if formulas referr to the paste area switch off the automated calculation of the worksheet: Application.ScreenUpdating=False
Application.Calculation=xlCalculationManual
In total it should somehow look like this:
Sub CopyFast ()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
ActiveSheet.Range("B1:B99") = ActiveSheet.Range("A1:A99")
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
But this really gets important when copying huge amounts of values e.g. in loops instead of the simple copying task in this example.

Related

Goal Seek based off cells with formulas

I'm trying to use goal seek across multiple sheets to updated the projects return on sale %. All of the cells have formulas and there is one cell that we hard code in order to tie back to our original return on sale %.
Below is the code I'm using, pretty straight forward.
for some reason when I run this macro its not giving me the desired value I would like for the return on sale %
Sheets("DEV INFAS WLKDN").Select
Range("F30").Select
Application.CutCopyMode = False
Application.CutCopyMode = False
Range("F30").GoalSeek Goal:=-0.002, ChangingCell:=Range("F19")
Sheets("NBN WLKDN").Select
Range("F30").Select
Application.CutCopyMode = False
Application.CutCopyMode = False
Range("F30").GoalSeek Goal:=-0.0062, ChangingCell:=Range("F19")
Sheets("MSIL LASER WLKDN").Select
Range("F30").Select
Application.CutCopyMode = False
Application.CutCopyMode = False
Range("F30").GoalSeek Goal:=-0.004, ChangingCell:=Range("F19")
Without knowing what value you're expecting and what its giving you, its hard to say why you might be getting an unexpected answer. The goal seek function in Excel is basically an iterative guessing function and is not guaranteed to return a globally optimal value. I don't have any documentation to support this claim but I'm pretty sure the goal seek function in Excel implements either a binary or golden-section search. To the best of my knowledge Excel doesn't specify what they are using under the hood, but these would be reasonable searches to use and looking into how they work might shed light on your issue.
Also, it looks like the length of your code could be reduced to
With ThisWorkbook
.Sheets("DEV INFAS WLKDN").Range("F30").GoalSeek Goal:=-0.002, ChangingCell:=Range("F19")
.Sheets("NBN WLKDN").Range("F30").GoalSeek Goal:=-0.0062, ChangingCell:=Range("F19")
.Sheets("MSIL LASER WLKDN").Range("F30").GoalSeek Goal:=-0.004, ChangingCell:=Range("F19")
End With
generally .Select is unnecessary and not recommended.

Shorten VBA code with repeat/loop

How do I shorten this code to repeat the task, but take less space? This code needs to run for like 27 more users. I know I am a total noob right now, but this would ease my workload for more than an hour daily...
Workbooks.Open ("https://blabla/Edgars/2017 Q3Q4/Edgars.xlsx")
Workbooks("Edgars.xlsx").Activate
Range("C24:AN27").Select
Selection.Copy
Workbooks("abc.xlsx").Activate
Sheets("Edgars").Activate
Range("C24:AN27").Select
ActiveSheet.Paste
Workbooks("Edgars.xlsx").Activate
Sheets("Edgars").Activate
Range("C33:AN36").Select
Selection.Copy
Workbooks("abc.xlsx").Activate
Sheets("Edgars").Activate
Range("C33:AN36").Select
ActiveSheet.Paste
Workbooks("Edgars.xlsx").Activate
Sheets("Edgars").Activate
Range("C42:AN45").Select
Selection.Copy
Workbooks("abc.xlsx").Activate
Sheets("Edgars").Activate
Range("C42:AN45").Select
ActiveSheet.Paste
Workbooks("Edgars.xlsx").Activate
Sheets("Edgars").Select
ActiveWindow.SelectedSheets.Delete
Workbooks("abc.xlsx").Activate
Sheets("Edgars").Select
Sheets("Edgars").Copy Before:=Workbooks("Edgars.xlsx"). _
Sheets(1)
Workbooks("Edgars.xlsx").Activate
Range("A1").Select
ActiveWorkbook.SaveAs Filename:="https://blabla/Edgars/2017 Q3Q4/Edgars.xlsx"
ActiveWorkbook.Close
Workbooks("abc.xlsx").Activate
Worksheets("TOOLS").Activate
Application.DisplayAlerts = True
Else
End If
Before you start tackling loops, or shortening the code, you will want to brush up on avoiding Select and Activate within VBA. Your code, in its current form, is difficult to read or improve because you are using a lot of implicit relationships.
For example:
Workbooks("Edgars.xlsx").Activate
Sheets("Edgars").Activate
Is actually:
Application.Workbooks("Edgars.xlsx").Activate
ActiveWorkbook.Sheets("Edgars").Activate
And can be changed to:
Application.Workbooks("Edgars.xlsx").Worksheets("Edgars").Activate
Of course, this doesnt eliminate the Activate problem, and you'll undoubtedly encounter an issue if 'Edgars.xlsx' is not an open workbook. This example isnt meant to solve your problem, it is only mean to point you in the right direction.
Once you refactor your code to eliminate the use of Activate, Select and the Implicit (unqualified) references, you can get yourself started with string variables. Something like this is valid code:
Dim UserName as String
UserName = "Edgars"
Application.Workbooks(UserName & ".xlsx").Worksheets(UserName).Activate
This allows your code greater flexibility, and gets you one step closer.
My recommendation would be to start here: How to avoid using Select in Excel VBA macros. Once you read this post, try implementing these steps within your code. Then read some more and try again.
Learning proper VBA takes a bit of a time investment, but if you can learn how to code VBA well you can save yourself much more time than just an hour (assuming you use Excel for more than just one process).
Best of luck!

VBA turning sections of a recorded macro into something more efficcient

I am trying to optimise some data sorting code, the original code looks like it has been "written" through the use of excels "Record Macro" function.
The following is an example from the code.
Range("A12").Offset(z, 0).Select
Selec.Resize(Selection.Rows.Count, Selection.Columns.Count + (X2 - 1)).Select
Selection.Copy
Range("C4").Offset(y, 0).Select
ActiveSheet.Paste
In order to make this code more efficient, should i re-write this section to involve a range variable that its' .Value is equal to the Selection data?
The X2, z and y variables are used as part of the copy function and are slowly increased to make reading the end product much easier. They are altered elsewhere in the module.
I would just like to see some suggestions for what you think I should do.
I have read the very popular "How to avoid using Select in Excel VBA Macros" question on here, and am just looking for some further advice.
(How to avoid using Select in Excel VBA macros)
Thanks
I guess this would be the easiest way.
Range("C4").Offset(y, 0).Resize(1, x2) = Range("A12").Offset(z, 0).Resize(1, x2)
Although I would advise:
to avoid .Offset and work with named ranges instead
to avoid .Copy and .Paste sometimes your data might be too big for your clipboard and using just the =-operator is way faster
to not name your variables with capital letters or additional ciphers, it can be very confusing
use this format .Cells( row, column ) instead of `.Cells("A1"). It's easier to handle and can be changed more easily via calculations
HTH
Copy/pasting isn't very efficient. Doing Range("X1").value = Range("Y1").value is better. This is what I would do
'change this
Selection.Copy
Range("C4").Offset(y, 0).Select
ActiveSheet.Paste
'to this
Range("C4").Offset(y, 0).Value = Selection.Value 'selection value is the range that is being copied.

Can I make this macro more efficient or faster?

I am brand new to coding. This macro runs slow and I'm hopeful that someone can help me clean it up. Thanks in advance for your help.
I developed the code to update my company's "Call Router" worksheet with new leads purchased from an outside source. The leads come to us in raw format in a worksheet called Fresh Agents Leads. Once the "Fresh Agent Leads" sheet is copied into the "MSS Call Routing Master List" file which houses the "Call Router" Worksheet, the macro reduces the raw data so that the parts we do not use are eliminated. It then re-formats what remains to match the formatting of the Old Call Router Worksheet and merges the two. It then renames the new Master sheet to Call Router.
The code is designed to start inside the workbook that houses the Fresh Agent Leads Sheet. The user is instructed to have both the Fresh Agents Leads File and the MSS Call Routing Master List opened on the desktop before executing the code.
Sheets("Fresh Agent Leads").Select
Sheets("Fresh Agent Leads").Copy After:=Workbooks( _
"MSS Call Routing Master List.xlsx").Sheets(1)
Columns("F:F").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A1").Select
Selection.Copy
Columns("F:F").Select
ActiveSheet.Paste
Columns("A:A").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlToLeft
Columns("C:C").Select
Selection.Delete Shift:=xlToLeft
Columns("E:E").Select
Selection.Delete Shift:=xlToLeft
Selection.Delete Shift:=xlToLeft
Columns("G:S").Select
Selection.Delete Shift:=xlToLeft
Rows("1:1").Select
Selection.Delete Shift:=xlUp
Columns("C:C").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("C1").Select
ActiveCell.FormulaR1C1 = "=CONCATENATE(RIGHT(RC[1],4))"
Range("C1").Select
Selection.AutoFill Destination:=Range("C1:C1048575")
Range("C1:C1048575").Select
Sheets("Call Router").Select
Rows("1:1").Select
Selection.Copy
Sheets("Fresh Agent Leads").Select
Rows("1:1").Select
Selection.Insert Shift:=xlDown
Application.CutCopyMode = False
Application.Run "PERSONAL.xlsb!MergeIdenticalWorksheets"
Columns("C:C").Select
Selection.NumberFormat = "0000"
Range("A:A,B:B,F:F").Select
Range("F1").Activate
Selection.ColumnWidth = 14
Columns("E:E").Select
Selection.ColumnWidth = 25
Columns("C:C").Select
Selection.ColumnWidth = 8.29
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Rows("1:1").Select
Selection.RowHeight = 30
With Selection
.VerticalAlignment = xlBottom
.WrapText = True
.Orientation = 0
.AddIndent = False
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorLight1
.TintAndShade = 0
.PatternTintAndShade = 0
End With
With Selection.Font
.ThemeColor = xlThemeColorDark1
.TintAndShade = 0
End With
Columns("D:D").Select
Selection.EntireColumn.Hidden = True
Range("E2").Select
ActiveWindow.FreezePanes = True
Sheets(Array("Call Router", "Fresh Agent Leads")).Select
Sheets("Call Router").Activate
ActiveWindow.SelectedSheets.Delete
Sheets("Master").Select
Sheets("Master").Name = "Call Router"
Range("C23").Select
ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True
ActiveWorkbook.Save
End Sub
A few tips:
Avoid .Select and .Activate as much as possible. Recording macros is a good start to VBA, but the first big step is leaving the "comfort zone" provided by these properties. In the beginning, they're good, but they're bound to create problems in the long run.
Read up on the following "basic" procedures: copying/pasting/inserting ranges, creating/deleting sheets, and determining the last rows/columns of a sheet or range that has relevant data. These three are your bestfriends. By learning these three by heart, you can manipulate a lot in Excel VBA.
After (2), start learning how to dimension variables and/or objects. Setting the jargon aside, this is basically just akin to giving each important thing you're working on "nicknames". Say you're working on 3 sheets. You don't want to keep on referring to ThisWorkbook.Sheets("Sheet1") and so on and on. You'd much rather want Sh1 or Sh2 instead.
Learn how to bunch similar procedures together using Union, With, or the like. This goes hand in hand with (1) above. You'll see an example later on this.
Application.ScreenUpdating - one of the best time-shaving tricks in Excel VBA.
Now, a few samples:
(1) Avoiding .Select || Learning to use the very nice .Copy one-liner
This part...
Range("A1").Select
Selection.Copy
Columns("F:F").Select
ActiveSheet.Paste
...can be reduced to:
Range("A1").Copy Range("F:F")
From four lines to just one. And it's much more readable. The second code snippet aboves basically reads, "Copy A1's value to the whole F column". Note that that's actually quite memory intensive, as in Excel 2010, you're actually pasting to a million and more rows with that command. Better be specific, like Range("F1:F1000").
(2) Bunching commands together
Bunching commands together in "written" VBA is different from the way you do it in macros. Since macros are recorded, everything is based on real time modifications. In "written" VBA, you can specify an action that will allow you to apply a single action on multiple objects. Let's say for example you want to delete Columns A and C while shifting all relevant data to the left.
When recording a macro to do this, you can select both A and C and delete them at the same time. However, most beginners take the safe path and record the deletion of columns one at a time which--while safe--is highly counterintuitive. Selecting both before deleting is the best option.
In written VBA, the second method above is a massive no-no (or at least, it's not the norm). Unless there's a specific and necessary reason, bunching similar commands together is the convention as it both eliminates error to a large degree and is not resource intensive.
In your code...
Selection.Delete Shift:=xlToLeft
Columns("C:C").Select
Selection.Delete Shift:=xlToLeft
Columns("E:E").Select
Selection.Delete Shift:=xlToLeft
Selection.Delete Shift:=xlToLeft
Columns("G:S").Select
Selection.Delete Shift:=xlToLeft
... is such a pain to read. We don't know why there are two deletions there, we don't know for sure where the data in Column S originally was, etc, etc. In instances like this, determining ahead of time the ranges you want to delete and executing the deletion is the perfect way.
Let's assume for example's sake that you want to delete the columns A, C, E, and F to O. A neat approach like follows will pull this off quite quickly and efficiently.
Union(Range("A:A"),Range("C:C"),Range("E:E"),Range("F:O")).Delete
Union is one of your early bestfriends. As with set notation in math, ranges you specify are put together into a set of ranges together and are actioned upon at the same time (in this case, .Deleted at the same time). Since the default shift is to the left, we can altogether remove the Shift:=xlToLeft line (another nifty VBA fact).
(3) With - one thing you cannot live without
At this point, you might be thinking, what about multiple actions on these ranges? We've only done single actions on multiple ranges and not the other way around. This is the point where With comes in. In this context, With will be used only on Ranges but it can be used on almost anything in VBA. Objects, ranges, external applications, etc. I will not delve on this, but suffice to say that using With is like using an anchor on something you want to work on with a few procedures.
In your code, we find...
Columns("C:C").Select
Selection.ColumnWidth = 8.29
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Rows("1:1").Select
Selection.RowHeight = 30
With Selection
.VerticalAlignment = xlBottom
.WrapText = True
.Orientation = 0
.AddIndent = False
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
... which can be reduced to:
With Columns("C:C")
.ColumnWidth = 8.29
.HorizontalAlignment = xlCenter
End With
With Rows(1:1)
.RowHeight = 30
.WrapText = True
End With
Basically, we did two things here. First, we anchored on Column C, and did two actions on it: set the column width, then the horizontal alignment. After anchoring to Column C and modifying it, we change the anchor to the whole of row 1 and we modify its height and set it to wrap text to cell width. From 24 lines, we've reduced that macro block to just 8 lines. How's that for brevity? :)
Why did I make without the other lines? As in the previous example (Union), we can make do with some lines that are either the default value anyway or are not modified. There will be exceptions to these, but they will be far and few and are a bit off your level for now. You'll get there.
(4) Creating/modifying sheets and avoiding .Activate, and a touch on dimensions
One of the pitfalls of beginners in VBA is that they use ActiveWorkbook, ActiveSheet, and .Activate a lot. This is not bad per se, but it's not good either. It's convenient to use, but it will cause a myriad of headaches if you incorporate it in really complex subroutines and functions.
To combat this, we first go into the idea of dimensioning or qualifying your objects. This is done by first declaring a keyword and then a data type. I will not delve into this further, as there are lots of VBA tutorials you can read for this, so I'll just point out some important ones.
Let's say you're working on two open workbooks. We can create a "nickname" for each of them so you can refer to them without having to type whole lines of reference.
Dim SourceWbk As Workbook
Dim TargetWbk As Workbook
The two lines above read as, "SourceWbk/TargetWbk is my nickname and I am dimensioned as a workbook, so I'll be expecting to be referred to a workbook". Now that we've created dimensions for them, we can point them to what they will stand for.
Set SourceWbk = ThisWorkbook
Set TargetWbk = Workbooks("I AM THE MASTER REPORT")
Note the "=" here. Now, we've basically declared that from now on, SourceWbk is going to refer to the workbook containing this code, and TargetWbk is going to refer to the open workbook named "I AM THE MASTER REPORT". Now let's look at the simple act of copying a sheet from SourceWbk to TargetWbk.
SourceWbk.Sheets("Sheet1").Copy After:=TargetWbk.Sheets("Sheet1")
Looks familiar? That's because this is pretty much the same as this recorded block of your code:
Sheets("Fresh Agent Leads").Select
Sheets("Fresh Agent Leads").Copy After:=Workbooks( _
"MSS Call Routing Master List.xlsx").Sheets(1)
Now, you can go one step further and name the sheets themselves, then copy them. Example follows:
Dim FAL As Worksheet 'Expects a worksheet.
Dim LastSheet As Worksheet
Set FAL = SourceWbk.Sheets("Fresh Agent Leads")
Set LastSheet = TargetWbk.Sheets("Sheet1") 'You can use a number index or specific name
FAL.Copy After:=LastSheet
At this point the code is very, very short and sweet already. No hassles, and the only effort you actually need is to remember what the "nicknames" refer to. Take note that there are specific words you should NOT be using as variable names. As much as possible, make it personalized but reasonable. Simply naming a sheet as Sh is good but it gets you nowhere in a file with 100 sheets each with different purposes.
(5) The Application Trickbook
In Excel VBA, there are a few things you can manipulate to increase the efficiency of your code. After all is said and done, a macro is just a repeated action. Running a recorded or a written one both will take you through the actions. .Select will select specific ranges and you'll see them get selected. .Activate will do the same, more or less. .Copy will show you those "ants" and the highlights they leave behind. All these contribute to a longer and often sloppy visual execution of the code. Herein steps the ScreenUpdating "trick".
Mind you, it's not really a trick. Most people consider them highly important parts of their code, but their inclusion into "layman" VBA modules are nonetheless helpful. One of the best practices is setting Application.ScreenUpdating = False at the beginning of a subroutine then setting it back to True at the end.
ScreenUpdating will "freeze" your screen, making everything happen without you seeing them. You won't see items getting copied or ranges getting selected. You won't see closed workbooks being opened and closed. While this only affects Excel when you call it, it's nonetheless invaluable.
A quick and dirty list (do not use this as an absolute reference!) of Application tricks:
.ScreenUpdating (False/True): Eliminates the visual updating of Excel when False. Absolutely necessary when copy-pasting or deleting rows.
.Calculation (xlCalculationAutomatic/xlCalculationSemiautomatic/xlCalculationManual): Similar to the Formulas > Calculation Options ribbon function, setting this to Manual will suspend all calculations. Highly recommended especially when you're updating ranges that are depended on by loads of VLOOKUP or INDEX formulas.
.EnableEvents(False/True): Disables triggering event based procedures. A bit advanced, but suffice to say that if you've got some automatic macro triggering on event-based changes, this will suspend them in favor of the current running macro.
There are loads of others and it will be to your best interest to learn most of them. ;)
THE BIG FINALE
Here's a sample code taken from your recorded macro that uses all the above techniques and takes into consideration the procedures you executed on your macro. This is not your whole code. Read this, test this, modify this and you'll improve a lot in a day.
Sub RefinedCode()
Dim SourceWbk As Workbook, TargetWbk As Workbook
Dim FALSht As Worksheet, FALSht2 As Worksheet, MasterSht As Worksheet
Application.ScreenUpdating = False 'We won't see the copy-paste and column deletion happening but they will happen.
Set SourceWbk = ThisWorkbook
Set TargetWbk = Workbooks("MSS Call Routing Master List")
Set FALSht = SourceWbk.Sheets("Fresh Agent Leads")
With TargetWbk
Set MasterSht = .Sheets("Master") 'Basically reads as Set MasterSht = TargetWbk.Sheets("Master")
FAL.Copy After:= .Sheets(1)
Set FALSht2 = .Sheets("Fresh Agent Leads")
End With
With FALSht2
Union(.Range("A:A"),.Range("C:C"),.Range("E:O")).Delete
With .Rows(1)
.RowHeight = 30
.WrapText = True
End With
.Range("A1").Copy .Range("F1:F100")
End With
MasterSht.Name = "Call Router"
TargetWbk.Save
SourceWbk.Close
Application.ScreenUpdating = True 'Return to default setting.
End Sub
Hope this helps.
I always use the following line
Application.ScreenUpdating = False
to turn off the screen updates which make the macro run much faster. Just add it in the beginning of your macro(s).
Awesome help here. I wish there was an easy way to stop the flicker when changing sheets ... Application.ScreenUpdating does not fully eliminate that in excel 2013 anyway.

copy and paste to table in a more efficient way

I have an excel file with 2 sheets:
1.INFO (huuuge table, around 10.000 rows)
2.ADD INFO
The second is where my issue is. Basically it has 2 functions, either filter (based on 2 different criteria) and search for info in the table and display it on that sheet or add a new row to the table. The macros i made work fine, but it seems weird to me that 1 minute is too long for it to complete the task:
Sub Search_in_table()
Dim header As Range
Sheets("ADD INFO").Select
Range("A13").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
If Worksheets("ADD INFO").[Item_to_search] = "Cust_ID" Then
Sheets("INFO").Select
Set header = [A1:Y1]
With header
.AutoFilter Field:=6, Criteria1:=Worksheets("INFO").[What_I_Want]
End With
ElseIf Worksheets("ADD INFO").[Item_to_search] = "ASIN" Then
Sheets("INFO").Select
Set header = [A1:Y1]
With header
.AutoFilter Field:=4, Criteria1:=Worksheets("INFO").[What_I_Want]
End With
End If
ActiveSheet.AutoFilter.Range.Copy
Sheets("ADD INFO").Select
Worksheets("ADD INFO").[A13].PasteSpecial
Sheets("INFO").Select
header.Select
Selection.AutoFilter
Sheets("ADD INFO").Select
End Sub
And this is the one to add a new row:
Sub add_esc()
Sheets("ADD INFO").Select
Range("Y9:A9").Select
Selection.Copy
Sheets("INFO").Select
Range("A1").Select
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Select
Selection.PasteSpecial
Sheets("ADD INFO").Select
Range("A9:Y9").Select
Selection.ClearContents
Is there a way to make them more efficient? Did i miss something? BTW, What_I_Want and Item_To_Search are just cells with names. An interesting fact is that during the writing of the code, i got very weird errors in things like "selection.paste", and that is why i was using a not common notation like "Worksheets("ADD INFO").[A13].PasteSpecial"
Any thoughts are greatly appreciated!!! Thanks in advance!
I'd recommend getting rid of "select" and "activate" wherever you can, should speed things up and ultimately avoid bugs. Are you able to just clear ALL cells on sheets("add info") for example? sheets("add info").cells.clear
As for the rest of the code: can't remember doing anything similiar but theory sounds OK... get rid of all those "selects" though, they just slow things down. Where you've got:
ActiveSheet.AutoFilter.Range.Copy
Sheets("ADD INFO").Select
Worksheets("ADD INFO").[A13].PasteSpecial
Instead just use this (and for extra credit, instead of using Sheets() refer directly to the sheets codename:
wsInfo.autofilter.range.copy wsAddInfo.cells(13,1) ' i.e. row 13, column 1 (col A)
Not sure about the rest of your question re: add rows etc, but using method above maybe you just need to increment that copy destination row? Or use application.worksheetfunction.counta(range) to find the last used cell rather than "select" etc...
There's the possibility that your method might actually be slower than just iterating over each row manually and copying where condition's met? Might be worth a try. Something like:
for each rgCell in rgList
if rgCell.offset(0,4) = stCrit1 _
and rgcell.offset(0,8) = stCrit2 then
rgcell.entirerow.copy wsAddInfo.cells(intDrawRow, intDrawCol)
intDrawRow = intDrawRow + 1
end if
next
And if all else fails, and i strongly recommend you get rid of all the "selects" in your code before doing this, use application.screenupdating = false at the start of your code, and application.screenupdating = true at the end of your code. Highly recommend error handling so that you set screenupdating back to true on errors too.
Cheers, Si