Excel crashes on workbook.close? - vba

I have a VBA function that will crash excel when I run it ("Microsoft Excel has stopped working"), but works fine if I step through each line in the editor. I want to open another workbook with the function, change the slicers on a given sheet, find a value, and then close the new workbook without saving it. The function I have is as follows:
Function ValueLookup()
Dim Check As Boolean
Dim NewBook As Workbook
Check = IsWorkBookOpen("C:\Location\Filename")
If Check = False Then
Set NewBook = Workbooks.Open("C:\Location\Filename")
Else
Set NewBook = Workbooks("Filename")
End If
NewBook.Activate
Worksheets("Sheetname").Activate
ActiveSheet.PivotTables("pivottable1")ManualUpdate = True
With ActiveWorkbook.SlicerCaches("Slicer_SlicerName")
.ClearManualFilter
.VisibleSlicerItemsList = Array("[Tablename].[Columnname].&[MyValue]")
End With
ActiveSheet.PivotTables("pivottable1").ManualUpdate = False
ValueLookup = ActiveSheet.Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
searchorder:=xlByRows, _
searchdirection:=xlPrevious, _
MatchCase:=False)
If Check = False Then NewBook.Close savechanges:=False
End Function
(IsWorkBookOpen() is taken from Detect whether Excel workbook is already open, and doesn't seem to present any issues).
It seems that trying to close the new workbook is what's causing the issue, and if the workbook is open before I run the function there is no issue. The subroutine that calls the function will normally execute the line after the function right before excel crashes (opening a MsgBox for user input). I have tried adding Sleep 1000 after each line and adding DoEvents after the last line with no change in results. I've tried changing
NewBook.Close savechanges:= False
to
Application.Windows("NewBook").Close
without any difference. I've also tried replacing the end with
If Check = False Then
Cancel = True
Application.OnTime Now, "Close_Xls"
End If
End Function
Sub Close_Xls()
ThisWorkBook.Close savechanges:=False
End Sub
but this closes the wrong workbook (the original one I'd like the macro to be run from) after my subroutine has finished. However, it does seem to execute the code successfully before closing the wrong workbook, and does not cause excel to crash.
Any suggestions?
Edit:
It now appears to work without issues. I changed the following:
If Check = False Then NewBook.Close savechanges:=False
End Function
To
NewBook.Saved = True
If Check = False Then
Cancel = True
Application.OnTime Now, "Close_Xls"
End If
End Function
Sub Close_Xls()
Workbooks("Filename").Close savechanges:=False
End Sub
Thanks!

Changing the Close_Xls() sub to the following will target the correct sheet to close:
Sub Close_Xls()
Workbooks("Filename").Close savechanges:=False
End Sub
Another way to close the workbook without saving that might work is to use:
NewBook.Saved = True
before closing.

Related

Excel VBA with Application.ScreenUpdating does not work

I have a macro in excel VBA which runs other macros. I am trying to implement Application.Screenupdating so that the user does not get to see what the macros do. However it seems to work for every macro, other than AccImport which is the main macro that I do not want my user to be aware of.
This macro does a spreadsheet transfer from excel to access, and I do not want my users to be aware of my access database. Within this macro it does a spreadsheet transfer by opening the access database, then closing it. Below is the main macro that I trigger, screenupdating=false seems to work for all the macros other than AccImport.
Any ideas? Thank you.
Sub ENTER1Dim2()
'
' ENTER1 Macro
'
'
If Worksheets("DIM21").Range("AR32") = 0 Then
MsgBox "Please enter DATA completely first"
End
Else
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!TransferE1Dim2"
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!PWDOFF"
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!ProtectE1Dim2"
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!UnprotectE2Dim2"
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!ClearE2Dim2"
Sheets("Data1").Select
Application.ScreenUpdating = False
Application.Run "'NEW.xlsm'!AccImport"
Sheets("DIM21").Select
Range("G41").Select
Application.Run "'NEW.xlsm'!PWDON"
Call AUTOSAVE
End If
Application.ScreenUpdating = True
End Sub
Macro below is AccImport.
Sub AccImport()
'Application.OnTime Now + TimeValue("00:01"), "AccImport"
Dim Acc As New Access.Application
Acc.OpenCurrentDatabase "C:\Users\yilmadu001\Desktop\Database.accdb"
Acc.DoCmd.TransferSpreadsheet _
TransferType:=acImport, _
SpreadSheetType:=acSpreadsheetTypeExcel12Xml, _
TableName:="Table1", _
Filename:=Application.ActiveWorkbook.FullName, _
HasFieldNames:=True, _
Range:="Data1$A1:BL40000"
Acc.CloseCurrentDatabase
Acc.Quit
Set Acc = Nothing
End Sub

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

changing sheet with macro causes sheet to freeze

My macro for changing sheets doesn't work anymore after I created a few UserForms. Thought the problem was the UserForms were not unloading properly but that doesn't seem to be the case.
When I click the button (which resides in a custom pop up menu) to go to another sheet it works but the sheet acts frozen, I can't scroll or highlight for example.
But if i change sheets by clicking on the tabs then everything is fine. So it would appear that my code to active another sheet is faulty.
My excel workbook has some UserForms, Worksheet_Change and Worksheet_SelectionChange events if that matters.
Is there a better way of doing this. Something that will obviously work and note freeze my sheet after it is activated?
Sheet goto Code:
Sub goto630()
Application.ScreenUpdating = False
Dim sht2 As Worksheet
Set sht2 = ThisWorkbook.Worksheets(2)
Dim sht3 As Worksheet
Set sht3 = ThisWorkbook.Worksheets(3)
sht3.Activate
sht3.Protect _
DrawingObjects:=False, _
Contents:=True, _
Scenarios:=False, _
UserInterFaceOnly:=True, _
AllowFormattingCells:=True
sht2.Visible = True
sht3.Visible = True
On Error GoTo 0
ActiveWindow.Zoom = 90
ActiveWindow.DisplayHeadings = True
ActiveWindow.DisplayHorizontalScrollBar = True
ActiveWindow.DisplayVerticalScrollBar = True
Application.DisplayFormulaBar = True
sht3.DisplayPageBreaks = False
ThisWorkbook.Worksheets(1).Visible = False
ThisWorkbook.Worksheets(4).Visible = False
ThisWorkbook.Worksheets(5).Visible = False
ThisWorkbook.Worksheets(6).Visible = False
ThisWorkbook.Worksheets(7).Visible = False
ThisWorkbook.Worksheets(8).Visible = False
Set sht2 = Nothing
Set sht3 = Nothing
Application.ScreenUpdating = True
End Sub
UserForm Code:
Private Sub UserForm_Click()
Application.OnTime Now + TimeValue("00:00:01"), "Finish"
Unload Me
Call Module2.ScreenRefresh
Exit Sub
End Sub
ScreenRefresh Module is just Application.ScreenUpdating = True read somewhere about this same problem that if the ScreenUpdating is in another module then when called it will fix the freeze issue.
Finish Module is activating the sheet again after the UserForm has been closed (also said to help the freeze issue).
It seems that Excel is waiting for me to click a cell before allowing me to scroll. How can I get around this?
Thanks for any help :)

VBA Excel macro message box auto close

I've an Excel macro that runs on opening the file, opens another excel file, refreshes the data, saves and then closes it.
I also have a middle bit (Dim AckTime) that displays a pop up message for second to show what it's done.
BUT.. Since I set the macro to run on opening the workbook using Public Sub Workbook_Open() the message box pops up but will not close automatically on 1 second anymore.
Can anyone help?
Public Sub Workbook_Open()
Application.ScreenUpdating = False Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
With Workbooks.Open("\\filename.xlsm")
ActiveWorkbook.RefreshAll 'updates the data
ActiveWorkbook.Sheets("Dashboard").Range("A2").Value = DateTime.Now
' updates this cell with the current time
Dim AckTime As Integer, InfoBoxWebSearches As Object
Set InfoBoxWebSearches = CreateObject("WScript.Shell")
AckTime = 1
Select Case InfoBoxWebSearches.Popup("Updated, saving & closing...", _
Case 1, -1
End Select
.Save
.Saved = True 'when saved..
.Close 0 'close the file
End With
End Sub
Select Case InfoBoxWebSearches.Popup("Updated, saving & closing...", AckTime)
Should be your only error. You just didn't set the wait time.

Printing faster in Excel

The print functionality of Excel (using VBA) is extremely slow. I'm hoping someone has a way of speeding the printing up (without using the Excel 4 Macro trick). Here's how I do it now:
Application.ScreenUpdating = False
With ActiveSheet.PageSetup
-various setup statements which I've already minimized-
End With
ActiveSheet.PrintOut
Application.ScreenUpdating = True
Yes, the PageSetup properties are very slow when you set them.
You have already set Application.ScreenUpdating = False, which is good, but an equally (or more) important step in this case is to set Application.Calculation = xlCalculationManual. (It is best if you save these settings and then restore them to the original at the end.)
Additionally, the property get for each PageSetup property is very fast, while it is only the property set that is so slow. Therefore, you should test the new property setting to make sure it isn't already the same as the existing property value in order to prevent an unnecessary (and expensive) call.
With all this in mind, you should be able to use code that looks something like the following:
Dim origScreenUpdating As Boolean
origScreenUpdating = Application.ScreenUpdating
Application.ScreenUpdating = False
Dim origCalcMode As xlCalculation
origCalcMode = Application.Calculation
Application.Calculation = xlCalculationManual
With ActiveSheet.PageSetup
If .PrintHeadings <> False Then .PrintHeadings = False
If .PrintGridlines <> False Then .PrintGridlines = False
If .PrintComments <> xlPrintNoComments Then .PrintComments = xlPrintNoComments
' Etc...
End With
Application.ScreenUpdating = origScreenUpdating
Application.Calculation = origCalcMode
Edit: A couple of updates:
For Excel 2010 and above you can make use of the 'Application.PrintCommunication' property, while for Excel 2007 and below, you can make use of 'ExecuteExcel4Macro'. For more details, see Migrating Excel 4 Macros to VBA.
For Excel 2007 and below, another interesting trick is to temporarily assign the printer driver to the 'Microsoft XPS Document Writer' and then set it back. Printing speed can improve by 3x. See: Slow Excel PageSetup Methods.
Hope this helps...
In furthering Michael's post and answering #rhc's question, the following code may also help you if need to copy Page Setup customizations from a single worksheet to multiple worksheets in a workbook:
Public Sub CopyPageSetupToAll(ByRef SourceSheet As Worksheet)
' Raise error if invalid source sheet is passed to procedure
'
If (SourceSheet Is Nothing) Then
Err.Raise _
Number:=vbErrorObjectVariableNotSet, _
Source:="CopyPageSetupToAll", _
Description:="Unable to copy Page Setup settings: " _
& "invalid reference to source sheet."
Exit Sub
End If
SourceSheet.Activate
With SourceSheet.PageSetup
' ...
' place PageSetup customizations here
' ...
End With
SourceSheet.Parent.Worksheets.Select
Application.SendKeys "{ENTER}", True
Application.Dialogs(xlDialogPageSetup).Show
End Sub
Alternatively, you could also modify the procedure to create a temporary worksheet to host your Page Setup changes, and then propagate those changes out to the other worksheets in your workbook:
Public Sub CopyPageSetupToAll(ByRef SourceBook As Workbook)
Dim tempSheet As Worksheet
' Raise error if invalid workbook is passed to procedure
'
If (SourceBook Is Nothing) Then
Err.Raise _
Number:=vbErrorObjectVariableNotSet, _
Source:="CopyPageSetupToAll", _
Description:="Unable to copy Page Setup settings: " _
& "invalid reference to source workbook."
Exit Sub
End If
Set tempSheet = SourceBook.Worksheets.Add
tempSheet.Activate
With tempSheet.PageSetup
' ...
' place PageSetup customizations here
' ...
End With
SourceBook.Worksheets.Select
Application.SendKeys "{ENTER}", True
Application.Dialogs(xlDialogPageSetup).Show
tempSheet.Delete
Set tempSheet = Nothing
End Sub
Due to the use of the SendKeys() function and Application.Dialogs functionality, this code does not offer the cleanest possible solution. However, it gets the job done. :)
if you want to have basicly the same page settings for every tab in a workbook can you speed things up by setting up one workshet and then copying that worksheet's settings somehow to the other worksheets? Is this possible?