I have created a simple macro to cut and paste data from one sheet to another and every once in a while I will get the Run time error 1004 cannot paste data error. It doesn't do it all the time.
Here is my current code:
Sub INSERTVE()
'
' INSERTVE Macro
'
' Keyboard Shortcut: Ctrl+Shift+I
'
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
ActiveSheet.DisplayPageBreaks = False
Application.ScreenUpdating = False
ActiveWorkbook.Names.Add Name:="newrowa", RefersToR1C1:=Rows(ActiveCell.Row)
Application.Goto Reference:="newrowa"
Application.Goto Reference:="NEWTRENDLOGITEM"
Selection.Copy
Application.Goto Reference:="newrowa"
Selection.EntireRow.Insert
Range("newrowa").Select
ActiveCell.Rows("1:1").EntireRow.Select
Application.Goto Reference:="insertsection"
Selection.Copy
Application.Goto Reference:="LASTROW"
Selection.EntireRow.Insert
ActiveWorkbook.Names.Add Name:="newrowZ", RefersToR1C1:=Rows(ActiveCell.Row)
Range("newrowZ").Select
ActiveWorkbook.Names("newrowZ").Delete
ActiveCell.Rows("1:1").EntireRow.Select
ActiveWorkbook.Names.Add Name:="newrowZ", RefersToR1C1:=Rows(ActiveCell.Row)
ActiveCell.Rows("1:1").EntireRow.Select
ActiveCell.Offset(0, 8).Range("A1").Select
Sheets("ve-01").Select
Application.Goto Reference:="newrowa"
ActiveCell.Rows("1:1").EntireRow.Select
ActiveCell.Offset(-1, 2).Range("A1").Select
Selection.Copy
Application.Goto Reference:="LASTROW"
ActiveCell.Offset(-13, 2).Range("A1").Select
**ActiveSheet.Paste link:=True**
Application.Goto Reference:="newrowa"
ActiveCell.Offset(-1, 3).Range("A1").Select
Selection.Copy
Application.Goto Reference:="LASTROW"
ActiveCell.Offset(-13, 3).Range("A1").Select
ActiveSheet.Paste link:=True
Application.Goto Reference:="LASTROW"
ActiveCell.Offset(-2, 16).Range("A1").Select
Selection.Copy
Application.Goto Reference:="newrowa"
ActiveCell.Rows("1:1").EntireRow.Select
ActiveCell.Offset(-1, 13).Range("A1").Select
ActiveSheet.Paste link:=True
Application.Goto Reference:="newrowa"
ActiveCell.Rows("1:1").EntireRow.Select
ActiveCell.Offset(-1, 1).Range("A1").Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("VE-01").Select
Range("newrowa").Select
ActiveWorkbook.Names("newrowa").Delete
ActiveWorkbook.Names("newrowz").Delete
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
ActiveSheet.DisplayPageBreaks = True
Application.Calculation = xlCalculationAutomatic
End Sub
Any suggestions or ideas on why it only does this once in a while? Any tips for a newbie on how to correct this? The code errors out when it gets to ActiveSheet.Paste link:=True
Thanks,
Related
I'm trying to get a loop with multiple if/else statements to work but it keeps saying either I have Ifs with no End Ifs or that I have a Loop with no Do.
Any pointers would be great.
Below is the what I've done so far, please go easy on me I only started trying to write in vba yesterday...
Sub EditTransposeCopy()
Sheets("Altered").Select
Dim count As Long
count = WorksheetFunction.CountA(Range("A6", Range("A6").End(xlDown))) - 1
Do While count > 0
If InStr(1, (Range("A23").Value), "Reason:") > 0 Then
Rows("9:11").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Rows("14").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Rows("16").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Rows("18").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Range("A7:A18").Select
Selection.Copy
Range("C6").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Range("A6:N6").Copy
Sheets("Output").Range("A" & Rows.count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Sheets("Altered").Select
Rows("6:18").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
count = count - 19
Else
If InStr(1, (Range("A20").Value), "Reason:") > 0 Then
Rows("9:11").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Rows("14").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Rows("16").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Range("A7:A16").Select
Selection.Copy
Range("C6").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Range("A6:L6").Copy
Sheets("Output").Range("A" & Rows.count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Sheets("Altered").Select
Rows("6:16").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
count = count - 16
Else
If InStr(1, (Range("A17").Value), "Reason:") > 0 Then
Rows("9:11").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Rows("14").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Range("A7:A14").Select
Selection.Copy
Range("C6").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Range("A6:J6").Copy
Sheets("Output").Range("A" & Rows.count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Sheets("Altered").Select
Rows("6:14").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
count = count - 13
Else
If InStr(1, (Range("A15").Value), "£0.00") > 0 Then
Sheets("Altered").Select
Rows("9:11").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
Range("A7:A12").Select
Selection.Copy
Range("C6").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Range("A6:H6").Copy
Sheets("Output").Range("A" & Rows.count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Sheets("Altered").Select
Rows("6:12").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
count = count - 10
Else
count = count - 10000000
End If
Loop
'
End Sub
Thanks in advance
Use ElseIf or terminate each If block with an End If
Sub EditTransposeCopy()
'...
Do While count > 0
If InStr(1, (Range("A23").Value), "Reason:") > 0 Then
'...
ElseIf InStr(1, (Range("A20").Value), "Reason:") > 0 Then
'...
ElseIf InStr(1, (Range("A15").Value), "£0.00") > 0 Then
'...
Else
'...
End If
Loop
End Sub
Welcome to SO, and welcome to VBA!
First up, you should look at how to avoid using select, because although this is how the macro recorder works, it's better practice (less prone to bugs) and more readable if you replace code like
Range("A1").Select
Selection.Copy
with
Range("A1").Copy
Secondly look up the syntax of an if statement - in particular this part about use of Else If will be handy in the above code. Each If requires it's own End If, looks like you missed a couple in your original code.
For a long time I'm not playing with VBA, so we have a spreadsheet on my work and checkng its code, I'm sure it can be improved.
Basically this spreadsheet has literally 200 buttons (100 to open and another 100 to close) and it copies the data from one sheet to another. Below are the examples of two of this macros.
Macro #1:
Sub IT100stop()
'
' newstop Macro
'
' Keyboard Shortcut: Ctrl+s
'
Application.ScreenUpdating = False
Range("G47").Select
ActiveCell.FormulaR1C1 = "DOWN"
Range("H47").Select
ActiveCell.FormulaR1C1 = _
"=YEAR(TODAY())&MONTH(TODAY())&DAY(TODAY())&HOUR(NOW())&MINUTE(NOW())&SECOND(NOW())"
Range("H47").Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:= _
xlNone, SkipBlanks:=False, Transpose:=False
Range("j47").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "=NOW()"
Range("j47").Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:= _
xlNone, SkipBlanks:=False, Transpose:=False
Range("K47").Select
Application.CutCopyMode = False
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "=IF(RC[-1]="""","""",IF(NOW()-RC[-1]<1,HOUR(NOW()-RC[-1])&"" h ""&MINUTE(NOW()-RC[-1])&"" m"",IF(DAYS(NOW(),RC[-1])<2,DAYS(NOW(),RC[-1])&"" day"",DAYS(NOW(),RC[-1])&"" days"")))"
Range("F47").Select
Application.ScreenUpdating = True
End Sub
Macro #2:
Sub IT100released()
'
' newreleased Macro
'
' Keyboard Shortcut: Ctrl+r
'
Application.ScreenUpdating = False
Sheets("Database").Select
Range("A2").Select
Application.CutCopyMode = False
Rows("2:2").Select
Selection.Insert shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Sheets("SINOPTIC").Select
Range("F47:U47").Select
Selection.Copy
Sheets("Database").Select
Range("A2").Select
Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:= _
xlNone, SkipBlanks:=False, Transpose:=False
Sheets("SINOPTIC").Select
Range("G47").Select
ActiveCell.FormulaR1C1 = "OK"
Range("H47:U47").Select
Selection.ClearContents
Application.ScreenUpdating = True
End Sub
The question is: what can we do to improve this code? If I add this following code before and after the actual macro code, will the calculations be faster?
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
'Macro Code
Application.EnableEvents = True
Application. DisplayStatusBar = True
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Thanks a lot!
Pay attention to what BigBen wrote: avoid the Select; that is the code created by the macro recorder, but it performs many unnecessary operations.
This is the "human" version of your macro # 2
Sub IT100released()
'
' newreleased Macro
'
' Keyboard Shortcut: Ctrl+r
'
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
Sheets("Database").Rows("2:2").Insert shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Sheets("SINOPTIC").Range("F47:U47").Copy
Sheets("Database").Range("A2").PasteSpecial Paste:=xlPasteValuesAndNumberFormats
Sheets("SINOPTIC").Range("G47") = "OK"
Sheets("SINOPTIC").Range("H47:U47").ClearContents
.EnableEvents = True
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
End With
End Sub
I have a Private sub which calls a specific macro on change in cell value. However, when it calls the macro, the macro runs party and then automatically switches to beginning of private sub without going through all the lines of the macro. Not sure why that is happening. I am not a pro in vba but have done lots of practice. So sorry if this sounds to be a stupid question. Thank you!
Regards,
Aanand
Here's the private sub:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("K2:N2")) Is Nothing Then
Call RetrieveActual
End If
End Sub
Here's the macro:
Sub RetrieveActual()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Sheets("Actual hours Database").Select
Range("A904857").End(xlUp).Offset(0, 7).Select
ActiveCell.FormulaR1C1 = "=RC[-7]&RC[-6]"
Selection.Copy
Range(Selection, Selection.End(xlUp)).Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
Sheets("Actual hours").Select
Range("C7").Select
ActiveCell.FormulaR1C1 = _
"=IFERROR(INDEX('Actual hours Database'!C3:C5,MATCH('Actual hours'!R5C&'Actual hours'!RC35,'Actual hours Database'!C8,0),MATCH('Actual hours'!RC2,'Actual hours Database'!R1C3:R1C5,0)),0)"
Selection.Copy
Range("C7:AG9").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("C11:AG13").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("C15:AG17").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("C19:AG21").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("C23:AG25").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("C27:AG29").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("C31:AG33").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("C35:AG37").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Range("C39:AG41").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
Sheets("Actual hours Database").Select
Columns("H:H").ClearContents
Sheets("Actual hours").Select
Range("A1").Select
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Use:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("K2:N2")) Is Nothing Then
Call RetrieveActual
End If
Application.EnableEvents = True
End Sub
NOTE:
As a matter of programming style for event code, I suggest:
always beginning and ending event code with the disable/enable
only exiting the code from the bottom
I have an issue with unprotecting / protecting a sheet when I run a macro. I read a few posts stating that I should insert the ActiveSheet.Unprotect Password:="my password" bit before and then the ActiveSheet.Unprotect Password:="my password", into the macro, but this has not worked. Any suggestions would be gratefully appreciated.
ActiveSheet.Unprotect Password:="my password"
Sheets("sheet1").Select
Sheets("sheet2").Visible = True
Sheets("sheet2").Select
Cells.Select
Selection.Copy
Workbooks.Add
Cells.Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, skipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Range("A1").Select
Application.DisplayAlerts = False
ActiveWorkbook.SaveAs Filename:="C:\file.csv" _
, FileFormat:=xlCSV, CreateBackup:=False
Application.DisplayAlerts = True
Application.DisplayAlerts = False
ActiveWorkbook.Save
Application.DisplayAlerts = True
Application.DisplayAlerts = False
ActiveWindow.Close
Application.DisplayAlerts = True
Sheets("Sheet2").Select
ActiveWindow.SelectedSheets.Visible = False
Sheets("sheet1").Select
ActiveSheet.Protect Password:="my password"
My code runs for about 5min and the goes into recovery error/message. I have posted 3 Call macros but have 40 in the code.
During the macro the cells need to calculate and I tried a time delay to help but no good.
Private Sub Worksheet_calculate()
If Range("$be8").Value = 1 Then
Application.EnableEvents = True
Call Macro1
Application.EnableEvents = False
End If
If Range("$bf8").Value = 1 Then
Application.EnableEvents = True
Call Macro2
Application.EnableEvents = False
End If
If Range("$bg8").Value = 1 Then
Application.EnableEvents = True
Call Macro3
Application.EnableEvents = False
End If
Sub Macro1()
'
'
Macro1 Macro
'
'
Sheets("Calc. 1").Select
Rows("11:11").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Application.Wait (Now + TimeValue("0:00:05"))
Rows("7:7").Select
Selection.Copy
Rows("11:11").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("B1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = ""
Range("B2").Select
Sheets("Calc.").Select
Range("A7:Q50002").Select
Selection.Copy
Range("A3").Select
ActiveSheet.Paste
Calculate
Range("AZ3").Select
Selection.Copy
Range("BA3").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("A1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = ""
Range("B1").Select
Workbooks.Add
DoEvents
End Sub
Sub Macro2()
'
' Macro2 Macro
'
'
Sheets("Calc. 1").Select
Rows("11:11").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Application.Wait (Now + TimeValue("0:00:05"))
Rows("7:7").Select
Selection.Copy
Rows("11:11").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("B1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = ""
Range("B2").Select
Sheets("Calc.").Select
Range("A8:Q50002").Select
Selection.Copy
Range("A3").Select
ActiveSheet.Paste
Calculate
Range("AZ3").Select
Selection.Copy
Range("BA3").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("A1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = ""
Range("B1").Select
Workbooks.Add
DoEvents
End Sub
Sub Macro3()
'
' Macro3 Macro
'
'
Sheets("Calc. 1").Select
Rows("11:11").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Application.Wait (Now + TimeValue("0:00:05"))
Rows("7:7").Select
Selection.Copy
Rows("11:11").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("B1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = ""
Range("B2").Select
Sheets("Calc.").Select
Range("A9:Q50002").Select
Selection.Copy
Range("A3").Select
ActiveSheet.Paste
Calculate
Range("AZ3").Select
Selection.Copy
Range("BA3").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("A1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = ""
Range("B1").Select
Workbooks.Add
DoEvents
End Sub
First, this is just a big pack of recorded macros, and therefore nearly unreadable, as hinted by Matt Webb in its excellent comment. That being said, I went to do some analysis.
The macros are strictly the same, besides the column of the Range("A7:Q50002").Select, which varies from 7 to 9 (and probably up to 46, if you really have 40 of those). Time to make a proper sub with a parameter :
Private Sub Worksheet_calculate()
If Range("$be8").Value = 1 Then
Application.EnableEvents = True
Call Macro(myRow)
Application.EnableEvents = False
End If
If Range("$bf8").Value = 1 Then
Application.EnableEvents = True
Call Macro(myRow)
Application.EnableEvents = False
End If
If Range("$bg8").Value = 1 Then
Application.EnableEvents = True
Call Macro(myRow)
Application.EnableEvents = False
End If
End Sub
Sub Macro(myRow)
Sheets("Calc. 1").Rows("11:11").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Application.Wait (Now + TimeValue("0:00:05"))
Rows("7:7").Copy
Rows("11:11").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("B1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = ""
'Range("B2").Select
Sheets("Calc.").Range("A" & CStr(myRow) & ":Q50002").Copy
Range("A3").Select
ActiveSheet.Paste
Calculate
Range("AZ3").Copy
Range("BA3").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Range("A1").Select
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = ""
'Range("B1").Select
Workbooks.Add
DoEvents
End Sub
it'still ugly, but now, you just have 1 main procedure instead of 40, and I cleaned a little bit. I also did comment the useless selects.
Next question : what does it do? Seems like it
inserts the row 11, then copies the row 7 into. That one shall not be problematic.
Copies a specific cell from another sheet to the current sheet. Well, why not.
Calculates. Here we have a problem. I have no clue of your calculations, and there very well might be circular things here, or insane amounts of calculations to do. Especially when I see hard-coded values going to the 50000th row... The wolf may hide here. Depends on your worksheet. This is my first suspect.
Copy another cell in the main sheet. No risk here.
Add an empty workbook. Without anything. Hum, are you sure? If your 40 values are positive, you dynamically open 40 workbooks, without naming them, or putting any data in them??? This is my second and last suspect.
Now, you have to troubleshoot yourself to know which suspect is guilty. For that, you can add breakpoints on a few strategic lines of the macro, to see what takes time(my bet on the calculate, but I may be wrong). Especially before & after the calculate & the Workbook.add
But ask yourself is everything I listed is useful, especially the calculate part, and especially the workbook.add part. Your macro might very well flood the computer memory with all those workbooks open in memory that are still useless.