Excel crashes after I run this macro - blank error report - vba

I am running this simple macro. The goal is to create new Data sheet on a click of a userform button (deleting the old one). After making a copy from a raw data sheet, it should rename it "Data". If sheet named "Data" already exists - delete it.
Private Sub CommandButton1_Click()
Dim ws1 As Worksheet
Dim trigger As Integer
trigger = 0
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For i = 1 To Sheets.Count
If Sheets(i).Name = "Data" Then
trigger = 1
Sheets("Data").Delete
Sheets("raw_Data").Visible = True
Set ws1 = Sheets("raw_Data")
ws1.Copy Sheets(Sheets.Count)
Sheets("raw_Data").Visible = False
End If
Next i
If trigger = 0 Then
Sheets("raw_Data").Visible = True
Set ws1 = ThisWorkbook.Worksheets("raw_Data")
ws1.Copy ThisWorkbook.Sheets(Sheets.Count)
Sheets("raw_Data").Visible = False
End If
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Unload Me
ActiveSheet.Name = "Data"
End Sub
Am I running some kind of infinite loop here? If I delete:
ActiveSheet.Name = "Data"
Excel isn't crashing any more.

I am with Ron on this one. I made a little bit cleaner version of the code and maybe it will shed some light to what the problem is.
Option Explicit
Private Sub CommandButton1_Click()
Const strDATA_SHEET As String = "Data"
Const strDATA_RAW_SHEET As String = "raw_Data"
Dim shDataRaw As Worksheet
Call TurnExtrasOff
' Check if we have the sheet data if so then delete it
If DoesWorksheetExist(strDATA_SHEET, ThisWorkbook) Then
Application.DisplayAlerts = False
ThisWorkbook.Sheets(strDATA_SHEET).Delete
Application.DisplayAlerts = True
End If
' Lets copy the raw data sheet.
Set shDataRaw = ThisWorkbook.Sheets(strDATA_RAW_SHEET)
shDataRaw.Visible = xlSheetVisible
shDataRaw.Copy ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
' Rename the sheet and hide raw data
ActiveSheet.Name = strDATA_SHEET
shDataRaw.Visible = xlSheetHidden
Call TurnExtrasOn
' Unload the user form
Unload Me
End Sub
' Procedure to turn extra features on
Sub TurnExtrasOn()
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = xlCalculationAutomatic
End With
End Sub
' Procedure to turn extra features oFF
Sub TurnExtrasOff()
With Application
.ScreenUpdating = False
.EnableEvents = False
.Calculation = xlCalculationAutomatic
End With
End Sub
' Function to check if a sheet exists
Function DoesWorksheetExist(ByVal sheetname As String, aWorkbook As Workbook) As Boolean
On Error Resume Next
DoesWorksheetExist = (Not aWorkbook.Sheets(sheetname) Is Nothing)
On Error GoTo 0
End Function
I hope this helps

Related

VBA Code takes too long to Run

Please see the below VBA Code that I've came up with. Essentially, this is to open another workbook, Unmerge the Rows, Copy the Columns and Paste it into my Active Workbook. However after copy pasting, when the code runs to the CalculationAutomatic line, it takes around 15mins. Is there any other way to make it more efficient?
Thank you
Option Explicit
Sub ImportRemarks()
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Dim PLPath As String
PLPath = Sheets("Instructions").Range("C16").Text
Dim wbThis As Workbook
Dim wbTarget As Workbook
Set wbThis = ActiveWorkbook
Set wbTarget = Workbooks.Open(PLPath)
wbTarget.Worksheets("Performance List").Select
Rows("1:2").Select
Selection.UnMerge
wbThis.Worksheets("keys").Range("I:I").Value =
wbTarget.Worksheets("Performance List").Range("F:F").Value
wbThis.Worksheets("keys").Range("J:L").Value =
wbTarget.Worksheets("Performance List").Range("P:R").Value
wbThis.Activate
Application.CutCopyMode = False
wbTarget.Close savechanges:=False
ActiveWorkbook.Sheets("Instructions").Select
Range("C22").Select
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Maybe something like as follows for starters. Ideally, the optimization steps would go in their own subs. One to switch on optimization at the start and the other to return everything to how it was at the end (or on error).
As requested, this shows you how to remove the .Select parts of your code by using With statements. It also includes a safe exit, in case of error, to switch back on everything you disabled.
Option Explicit
Public Sub ImportRemarks()
Dim PLPath As String, wbThis As Workbook, wbTarget As Workbook
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.EnableEvents = False
On Error GoTo Errhand
Set wbThis = ThisWorkbook
Set wbTarget = Workbooks.Open(PLPath)
PLPath = wbThis.Worksheets("Instructions").Range("C16").Text
wbTarget.Worksheets("Performance List").Rows("1:2").UnMerge
With wbThis.Worksheets("keys")
.Range("I:I") = wbTarget.Worksheets("Performance List").Range("F:F")
.Range("J:L") = wbTarget.Worksheets("Performance List").Range("P:R")
End With
wbTarget.Close savechanges:=False
With wbThis
.Activate
' .Worksheets("Instructions").Range("C22").Activate '<=consider whether this is needed?
End With
Errhand:
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
More info on optimization here:
https://www.thespreadsheetguru.com/blog/2015/2/25/best-way-to-improve-vba-macro-performance-and-prevent-slow-code-execution
http://www.cpearson.com/excel/optimize.htm

Retain cutcopy mode after macro

So I have this problem which I can't wrap my head around.
I have a an excel report that executes an important macro on sheet_activate, and as we all know macros cancel CutCopyMode.
Therefore, if I want to copy & paste something from a different file into my report, it never works because as soon as I activate my report it runs the macro and cancels the CutCopyMode from the other file.
Things I have tried:
1) save cutcopymode value and re-activate it after the macro:
Dim tmpCT
tmpCT = Application.CutCopyMode
...
Application.CutCopyMode = tmpCT
the problem: it doesnt work.
2) save the data from the clipboard and re-insert it as plain text object after the macro is done running:
Dim DataClipBoard As String
Dim clipboardData As DataObject
Dim RangeCopied As Range
Set RangeCopied = Selection
DataClipBoard = ClipBoard_GetData
Application.CutCopyMode = False
...
Set clipboardData = New DataObject
With clipboardData
.SetText DataClipBoard
.PutInClipboard
End With
Set clipboardData = Nothing
The problem: it's plain text and doesn't retain formats/links/etc.
I'd appreciate any input you can give me on this issue.
The following macro will return the current range for Cut/Copy, which you can then store in a Range variable and re-Cut/Copy after your other workbook is open.
(Personally, I think that Application.CutCopyRange should be a built-in special variable to do this.)
Function CutCopyRange() As Range
Dim StoredMode As XlCutCopyMode
StoredMode = Application.CutCopyMode
If StoredMode < 1 Then Exit Function 'Null case
If StoredMode = xlCut Then
'Disappointing, since Clipboard lets you Paste a copy of a cut range...
MsgBox "Unfortunately, Worksheet.Paste(Link:=True) only works for Copy-mode.", vbCritical
Exit Sub
End If
Dim ScreenUpdating As Boolean, DisplayAlerts As Boolean, EnableEvents As Boolean
ScreenUpdating = Application.ScreenUpdating
DisplayAlerts = Application.DisplayAlerts
EnableEvents = Application.EnableEvents
Application.ScreenUpdating = False
Application.EnableEvents = False
'This makes us loose our Cut/Copy mode...
With Worksheets.Add
.Paste Link:=True
Set CutCopyRange = Range(Range(Replace(Selection.Cells(1, 1).Formula, "=", "")), _
Range(Replace(Selection.Cells(Selection.Rows.Count, Selection.Columns.Count).Formula, "=", "")))
Application.DisplayAlerts = False
.Delete
End With
'Restore Cut/Copy mode to what it was before the previous block
Select Case StoredMode
Case xlCut
CutCopyRange.Cut
Case xlCopy
CutCopyRange.Copy
End Select
Application.DisplayAlerts = DisplayAlerts
Application.ScreenUpdating = ScreenUpdating
Application.EnableEvents = EnableEvents
End Function

buttons not copying with sheet excel vba

I have some macros that copy my sheet in excel,and delete certain data. Unfortunately the buttons to which the macros are assigned do not copy over when the macros are run.
Sub CandD()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim sh As Shape, strtSh As Worksheet
Set strtSh = ActiveSheet
Sheets("BM Condition").Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = "BM Condition" & Sheets.Count - 1
Range("E14:E33,I14:I33,M14:M33").ClearContents
For Each sh In ActiveSheet.Shapes
sh.Delete
Next sh
strtSh.Select
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
This is the macro I am using. I have very limited VBA experience and am not finding google very helpful. Could someone recommend a fix for my buttons not copying over?
EDIT: I forgot to mention that when manually copying the buttons remain. I am not sure why this is.
As FunThomas mentioned, I've tried and tested the following without any errors:
Sub CanD()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim sh As Shape, strtSh As Worksheet
Set strtSh = ActiveSheet
Sheets("BM Condition").Copy After:=Sheets(Sheets.Count)
ActiveSheet.Name = "BM Condition" & Sheets.Count - 1
Range("E14:E33,I14:I33,M14:M33").ClearContents
strtSh.Select
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

Copying existing password protected sheet to new workbook as an unprotected sheet does not make the new worksheet unprotected

Copying an existing password protected sheet to a new workbook as an unprotected sheet gives the following error when user tries to type in data in the new worksheet.
Error: "the cell or chart you're trying to change is on a protected sheet"
Click OK on the error message.
Please note that this error happens only once. click OK on the pop up error message and type again, then excel allows you to type data in the cells and save the sheet.
We have an excel (format .xls) file currently being used to create another excel spreadsheet when a button on a form in the same spreadsheet is clicked. It basically copies one password protected blank sheet (a template) to a new workbook as an unprotected sheet. The code below used to work with excel 2007(using .xls format). We recently upgraded from excel 2007 to excel 2013 and the problem appeared.
Private Sub cmd_Click()
Dim jBook As Workbook
Dim jsheet As Worksheet
CurrentWorkBook = ActiveWorkbook.Name
Workbooks(CurrentWorkBook).Unprotect jWorksheetPassword
'catch all for errors
On Error GoTo ErrEnd
Dim orginalScreenUpdating As Boolean
orginalScreenUpdating = Application.ScreenUpdating
Application.ScreenUpdating = False
If Range("Language").Value = "2" Then
'French
Set jsheet = TemplateFR
Else
'english
Set jsheet = TemplateEN
End If
jsheet.Visible = xlSheetHidden
'jSheet.Visible = xlSheetVisible
'Delete this line
jsheet.Unprotect jWorksheetPassword
Set jBook = Workbooks.Add(xlWBATWorksheet)
jsheet.Copy After:=jBook.Sheets(1)
jBook.Sheets(2).Visible = xlSheetVisible
Application.DisplayAlerts = False
jBook.Sheets(1).Delete
Application.DisplayAlerts = True
jsheet.Visible = xlSheetVeryHidden
'Delete this line
jBook.Sheets(1).Unprotect jWorksheetPassword
'Delete this line
'jsheet.Protect Password:=jWorksheetPassword
NoErrEnd:
Workbooks(CurrentWorkBook).Protect Password:=jWorksheetPassword, Structure:=True, Windows:=False
Application.ScreenUpdating = orginalScreenUpdating
Unload Me
Exit Sub
ErrEnd:
Workbooks(CurrentWorkBook).Protect Password:=jWorksheetPassword, Structure:=True, Windows:=False
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox DataTable.Range("MSG4").Value, vbCritical, DataTable.Range("MSG4TITLE").Value
Unload Me
End Sub
The following lines of code activate the original workbook and this somehow clears the protection of the copied sheet with excel 2013 only. On Excel 2007 this causes the original workbook to be activated and confuses users, hence the check for 2013.
If Application.Version = "15.0" Then
Workbooks(CurrentWorkBook).Activate
'jBook.Activate
End If
This is a hack that happens to work. If some one finds a better solution please do post it here as well.
The full code listing is as follows:
Private Sub cmd_Click()
Dim jBook As Workbook
Dim jsheet As Worksheet
CurrentWorkBook = ActiveWorkbook.Name
Workbooks(CurrentWorkBook).Unprotect jWorksheetPassword
'catch all for errors
On Error GoTo ErrEnd
Dim orginalScreenUpdating As Boolean
orginalScreenUpdating = Application.ScreenUpdating
Application.ScreenUpdating = False
If Range("Language").Value = "2" Then
'French
Set jsheet = TemplateFR
Else
'english
Set jsheet = TemplateEN
End If
jsheet.Visible = xlSheetHidden
Set jBook = Workbooks.Add(xlWBATWorksheet)
jsheet.Copy After:=jBook.Sheets(1)
jBook.Sheets(2).Visible = xlSheetVisible
Application.DisplayAlerts = False
jBook.Sheets(1).Delete
Application.DisplayAlerts = True
If Application.Version = "15.0" Then
Workbooks(CurrentWorkBook).Activate
'jBook.Activate
End If
jsheet.Visible = xlSheetVeryHidden
NoErrEnd:
Workbooks(CurrentWorkBook).Protect Password:=jWorksheetPassword, Structure:=True, Windows:=False
Application.ScreenUpdating = orginalScreenUpdating
Unload Me
Exit Sub
ErrEnd:
Workbooks(CurrentWorkBook).Protect Password:=jWorksheetPassword, Structure:=True, Windows:=False
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox DataTable.Range("MSG4").Value, vbCritical, DataTable.Range("MSG4TITLE").Value
Unload Me
End Sub

Excel VBA Delete Column from imported worksheet

I am using this code to import a worksheet from a closed file. Once the import is complete I want to delete a column from that worksheet and switch back to the primary worksheet. I tried using Columns(4).Delete and EntireColumns.Delete but there is no error and Excel takes no action. Any ideas on a better way I could do this?
'THIS CODE HANDLES THE IMPORT OF THE DATA
Sub ImportFile()
'DEFINITIONS
Dim fileImport As String
Dim srcBook As Workbook
' TURNS OFF SCREEN UPDATING
Application.ScreenUpdating = False
Application.EnableEvents = False
' THE FILE PATH
fileImport = "PATH"
'OPENS THE BOOK
Set sourceB = Application.Workbooks.Open(fileImport)
'COPYS THE SHEET
sourceB.Sheets("Miscellaneous Holds").Copy After:=ThisWorkbook.Sheets (ThisWorkbook.Sheets.Count)
' CLOSES THE BOOK
srcBook.Close True
'ENABLES SCREEN EDIT
Application.ScreenUpdating = True
Application.EnableEvents = True
Sheets("Main").Activate
End Sub
This maybe not working if you are not qualifying the sheet properly in your Columns(4).EntireColumn.Delete statement...
So use sourceB.Sheets("Miscellaneous Holds").Columns(4).EntireColumn.Delete instead....
If you don't want these changes to be saved in your source workbook then change the saveChanges parameter to false.
'THIS CODE HANDLES THE IMPORT OF THE DATA
Sub ImportFile()
'DEFINITIONS
Dim fileImport As String
Dim srcBook As Workbook
Dim srcSheet As Worksheet
' TURNS OFF SCREEN UPDATING
Application.ScreenUpdating = False
Application.EnableEvents = False
' THE FILE PATH
fileImport = "PATH"
'OPENS THE BOOK
Set srcBook = Application.Workbooks.Open(fileImport)
Set srcSheet = sourceB.Sheets("Miscellaneous Holds")
srcSheet.Columns(4).EntireColumn.Delete
'COPYS THE SHEET
srcSheet.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
' CLOSES THE BOOK
srcBook.Close False
'ENABLES SCREEN EDIT
Application.ScreenUpdating = True
Application.EnableEvents = True
ThisWorkbook.Sheets("Main").Activate
End Sub