VBA Paste values - Response time - vba

I have a code that copies one range to another
rng1.Copy Destination:=rng2
However I only want the values, not all the formatting, so I have the below which works to achieve this
rng1.Copy
Application.ScreenUpdating = False
rng2.PasteSpecial Paste:=xlPasteValues
Application.ScreenUpdating = True
However, the processing speed of this is painfully slow. The sheet grinds to a halt for quite a long time compared to the instant response of the 1st formula.
Is there a method of amending the 1st formula to paste values only? I was unable to find a way in similar questions about pasting values....
Alternatively, is there another method that is quicker than using the 2nd formula?

copy & paste is notoriously slow in VBA, better to just assign directly, assuming both ranges are the same size
rng2.value = rng1.value

Related

VBA copy sheet from one workbook to another (values and format only)

I have the following code to copy and paste one sheet from one wb to another:
wb1.Worksheets("ws").Copy After:=wb2.Sheets(wb1.Sheets.Count)
I'm trying to only paste values and formatting, how would I go about doing this?
Also the process is taking a longer that expected time, possibly because the sheet I'm copying from contains a pivot table with a large amount of data. Is there anyway I can speed it up?
Thanks for the help!
In terms of efficiency. Copy & Pasting is slower than setting Rng2.Value to being Rng1.Value and then using .NumberFormat etc to make Rng2 like Rng1. You'd have to do Worksheets.Add first.
Rng2.Value = Rng1.Value
Rng2.NumberFormat = Rng1.NumberFormat
Do you want fonts etc as well?
If you want to do Copy & Paste then you could do paste-special values and then paste-special formats but that'll be slower.
If you literally just want the values, you can skip copy/paste (and thus using the clipboard) altogether by setting two ranges equal to eachother:
=Range([copy TO range]).Value = Range([copy FROM range]).Value.
But you are adding the worksheet at the same time, so add a line that creates the blank worksheet, then do
wb2.sheets([worksheet name]).Value = wb1.worksheets("ws").value

Copy/Paste variable dataset between workbooks without clipboard

I've been trying to optimize some of my coding and managed to cut and speed it up a lot. However there are some things that are still quite clunky (and me still a noob). Backstory is that my code is opening source and target files, copies a lot of data of variable length, closes source and then does a lot of operations and finally saves target file.
One of the things Id like is to do if possible is a direct copy of data without using clipboard, activating workbooks, selecting sheets (whatever of this is possible to pack into more efficient code that I am currently having)
Windows("SOURCE.xlsm").Activate
Sheets("Data").Select
Range("A2:AX10").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Windows("TARGET.xlsm").Activate
Range("A2").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Is it possible to do a selection (A2:AX10 and all the way down to last row) in SOURCE file-Data sheet and directly copy it to TARGET file-Data sheet cell A2 without using clipboard.
The reason why I use A2:AX10 and then selection down is because I have a lot of blank cells in the whole data set and this way I get entire data.
I would like to be able to to that selection and use it as a range in this line
Workbooks(“SOURCE”).Worksheets("Data").Range(“A2:AX10 & ALLTHEWAYDOWN”).Copy _Workbooks(“TARGET”).Worksheets("Data").Range(“A2")
I was trying to solve this but I dont end up with desired result. When I try doing selection and setting as range then both trying copy range with activitng workbooks and in the direct copy mode I get 1004 error.
Is it possible to optimize this chunk and make it work. It would improve a lot of my VBA.
Thanks,
You need something like this:
With Workbooks("SOURCE.xlsm").Sheets("Data")
.Range("A2:AX10", .Range("A2:AX10").End(xlDown)).Copy Workbooks("TARGET.xlsm").ActiveSheet.Range("A2")
End With
You could probably also use CurrentRegion rather than End(xlDown
You can set one range's values (the range where you would want to paste values) equal to a source range's values (the range which you would previously have copied).
Sub paste_values()
Dim wb_A As Workbook, ws_A As Worksheet
Dim wb_B As Workbook, ws_B As Worksheet
Dim last_row As Long
Set wb_A = ThisWorkbook
Set ws_A = wb_A.Sheets(1)
Set wb_B = Workbooks("WorkbookB")
Set ws_B = wb_B.Sheets(1)
With ws_A
last_row = .Range("A" & .Rows.Count).End(xlUp).Row
End With
ws_B.Range("A2:AX" & last_row).Value = ws_A.Range("A2:AX" & last_row).Value
End Sub
This code is setting the new range's values equal to the original range. It prevents the need to activate sheets or workbooks, whilst also copying data to a range without filling the clipboard.
I would also recommend using last_row = .Range("A" & .Rows.Count).End(xlUp).Row to find the last row of your data. Although you do need to ensure you use this on a column which you know contains continuous data.

Looping the whole cells to change a specific formula issue

I'm writing a function to change an entire column to new values using a formula, here's the code I'll elaborate more on the idea down there.
The problem is that it hangs and I have to rerun Excel and I'm not sure why.
Sub Button2_Click()
Dim i As Long
For i = 2 To Rows.Count
Cells(i, 4).Formula = "=B" & i & "+6*3600000/86400000+25569"
Next i
End Sub
So what's this about? I'm changing the fourth column to excel time because what I have in column B is epoch time, and this is the formula I'm using, it works with my case if I tried one by one, but for some reason it won't work as a whole. I'm not sure what's done wrong? But I'd appreciate your help.
Writing to cells one-by-one is very slow.
Writing formulas one-by-one is slower still, because each must be evaluated before Excel accepts them as formulas.
Doing this a million times can literally freeze Excel.
The solution is to write them all in one shot (no loops):
Sub Button2_Click()
[d2:d1048576] = "=B2+6*3600000/86400000+25569"
End Sub
' Another way of doing mass calculation is by using copy and paste method.
It will be better to convert the columns into values so that the sheet won't calculate again and again. It helps to prevent the sheet from hanging issues
Sub Button2_Click()
Range("D2").Formula = "=b1" & "+6*3600000/86400000+25569"
Range("D2").Copy
Range("D2:d1048576").PasteSpecial xlValues
Application.CutCopyMode = False
Range("D:D").Value = Range("D:D").Value
End Sub

Excel to replace formulas with values

I have an Excel workbook (1) with around 9 sheets that is pulling in and manipulating data from a second workbook (2).
After pulling in the data from workbook (2) I need to be able to replace the formulas in workbook (1) to the resulting values that the formulas have produced, from here I will then save the workbook (1) with the results.
Is there a macro that can do this for me?
On your new workbook some basic code such as:
Sub Value()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Sheets
ws.UsedRange.Value = ws.UsedRange.Value
Next
End Sub
While the OP is dated, I want to make note of a non-loop method that is useful. In certain scenarios, loops can really slow down the code execution. To replace formulas in a cell --without a loop-- try:
With Sheets("example").Range("A1:C1000")
.value = .value
End With
You can revise the reference as necessary, but the execution is seamless, fast, and as a bonus - prevents range highlighting that cannot be cleared if you pursued the .copy + .pastespecial xlPasteValues approach.
What seems to work for me is to use concatenate()
So, for example, the formula I have referencing a cell from another sheet is:
=arrayformula(iferror(index('To Be Processed'!X:X,small(if($A$1='To Be
Processed'!$Y2,row('To Be Processed'!X:X)),row((2:2))),"")))
and if I change to the formula to:
=concatenate(arrayformula(iferror(index('To Be
Processed'!X:X,small(if($A$1='To Be Processed'!$Y2,row('To Be
Processed'!X:X)),row((2:2))),""))))
and it puts in the text value from the reference cell into my second sheet.
Which may or may not be helpful depending on how you populate your sheets--I'm not very good with VBA, though, which means I do more things manually :)

VBA Excel Copy Table Values only to another sheet

I am trying to copy only the values from a table to a different sheet, however the below code is only copying the formulas thus losing references. I have tried different solutions such as adding .Value to .DataBodyRange.Copy Cells(i,1) however didn't work.
Thanks for your help
Sub loadData()
Application.AutoCorrect.AutoFillFormulasInLists = False
Dim wsh As Worksheet, i&
Application.ScreenUpdating = 0
With ActiveSheet.ListObjects(1)
If ActiveSheet.FilterMode Then .Range.AutoFilter
.DataBodyRange.Delete
i = 4
For Each wsh In ThisWorkbook.Worksheets
If wsh.Name <> "Template" Then
With wsh.ListObjects(4)
.DataBodyRange.Copy Cells(i, 1)
i = i + .ListRows.Count
End With
End If
Next wsh
.Range.AutoFilter Field:=5
End With
Application.ScreenUpdating = 1
End Sub `
This question might help you. Try changing the format (values or formulas) when pasting the values using pastespecial.
You are already using loops to accomplish your checks. You should use loops to finish the job and don't worry about using the clipboard to copy and paste. I can understand using copy and paste especially if you don't understand loops, but you clearly do.
You can do another loop where you set the values for the cells one at a time.
LastCol = Sheets("Sheet1").Cells(1, Columns.count).End(xlToLeft).Column 'Get last column of row with data
For col = 1 To LastCol
Sheets("Sheet2").Cells(i, col).Value = Sheets("Sheet1").Cells(i, col).Value
Next col
This isn't a complete solution, but if you insert this into your code where you are trying to copy and paste, you should get a good idea of how to complete this. Again, I'd avoid using copy and paste macros, simply because it's quicker to just write a three or four line loop in VBA than to record a macro, then edit it, clean it up, modify it, and debug it. It sure seems like less work to "record a macro" but in my experience, the code is quicker and more accurate. You know exactly what is happening instead of some parameters you might not want to question and don't know what they do.