Cannot close workbook after running sub with userform - vba

I have a macro that opens a userform to capture a start and end date. After clicking OK on the userform, a file dialog box opens to select an Excel Workbook to open.
Immediately after I run the below sub, I can't close the workbook that is opened by using the 'X' in the top-right corner. I also can't save the workbook by clicking the save icon.
However, if I click on another workbook or switch to a different sheet in the workbook that was opened, and then click back to the one opened by the sub everything works as it's supposed to.
Also, I replace the userform with two input boxes, to capture each of the two dates, I am able to close the workbook that is opened with no issue.
Maybe there's something funny with the userform code?
This is all that is in the userform.
Private Sub Ok_button_Click()
call module1.forecast
unload userform1
end Sub
And this is the main sub.
Sub forecast()
dim start_SFY as long
dim end_SFY as long
dim filesToOpen as object
dim wb as workbook
Application.ScreenUpdating= False
start_SFY = userform1.textbox1.value
end_SFY = userform1.textbox2.value
set filesToOpen = application.fileDialog(msoFileDialogOpen)
filesToOpen.show
set wb = application.workbooks.open(filesToOpen.selecteditems(1),false)
Application.ScreenUpdating= True
End Sub
Here's the sub showing userform1
Sub run_userform()
userform1.show
End Sub
Also, here is the Excel version:
Excel 2013 64-bit (15.04753.1003) Part of Microsoft Office 365 ProPlus
Can someone maybe try to replicate the issue that I'm having? I'm wondering if this is an issue related to my employer's version of Excel or something?
This sort of thing has never happened to me before.
Also, I can close the program with VBA. It's just when trying to click the 'X' that it won't close.
Update:
I was able to get the code, with no changes, to work fine at home on Excel 2016. I'm going to get a coworker to test on their system today.
When I was home, I didn't put a button to call the sub on a worksheet. I called it from the VBA editor. After some testing this morning, it seems that the button is the issue. If I call the sub from the VBA editor, I can close the opened workbook. However, if I use a command button (form control, not ActiveX as I get an error saying, "Cannot draw object" whenever I try to add any kind of ActiveX object to a worksheet) the opened workbook will not close.
I think I have found the problem
This issue seems to be with the 'form control command button'. ActiveX was disabled in the Trust Center. When I enabled it and created a command button, I was able to close the opened workbook. I then tried the command form button again, and could not close the opened workbook. I was also successfully able to close the opened workbook when I ran the sub from the sub listbox in the developer tab, and when I place the sub in the Excel Ribbon and ran it from there.
Any idea as to why the control form command button would cause this issue?

The root of the problem is the change to using multiple excel interfaces in 2013. Microsoft addresses the issue in the Solutions for SDI Issues section of this page.
A workbook cannot be closed by clicking the red "X" Close button when
that workbook is programmatically opened via a modal user form. To
work around this issue, it is suggested that you add the following
code to the user form Layout event procedure and then open the user
form as modeless
Private Sub UserForm_Layout()
Static fSetModal As Boolean
If fSetModal = False Then
fSetModal = True
Me.Hide
Me.Show 1
End If
End Sub
Another option is to open the workbook window, activate any other
window, and then reactivate the workbook window. You should now be
able to close the workbook using the Close button.
So these are the two options they present and one I came up with.
Option 1) You can switch your dialog to modeless using their code, or by setting the ShowModel property to false in your userform.
Option 2) As you discovered, manually switching between workbooks after opening via modal userform resyncs everything. Not a good solution for the users of my code, and I don't recommend relying on it.
Option 3) It's worth mentioning, if you don't open the file via the userform then there's no issue. So if last thing the userform needs to do is open the file, you can easily save the file path in a string, unload the troublesome userform and move the workbooks.open call after closing. Here's an example of what I mean
Public EDIT_FILE_DIRECTORY As String
Public Sub Main()
fileOpenerForm.Show
If EDIT_FILE_DIRECTORY <> "" Then
Call Workbooks.Open(EDIT_FILE_DIRECTORY)
End If
End Sub
And in the userform something along these lines, where the filename is created based on userform parameters and a listbox selection:
Private Sub OpenSelectedWorkbooks_Button_Click()
Dim workbookName As String
workbookName = selectionList.Item(Me.FileSelection_ListBox.ListIndex + 1)
EDIT_FILE_DIRECTORY = ROOT_DIR & GetSelectedSubfolder & "\" & workbookName
Unload Me
End Sub

Try fileOpenerForm Show 0 to open open it with Modal = False (Makes the macro run while the Userform is visible)
Do not forget to add fileOpenerForm.Hide later on.
Also Load fileOpenerForm and Unload fileOpenerForm may be useful

Related

Pause VBA Word macro, allow user to make a selection, and restart where it left off

I have a requirement for VBA script in Microsoft Word to pause so that the user can select text that will be copied to the clipboard so that it can exported to an Excel file. The user will make a number of selections and finally indicate he/she is done when the contents of the clipboard will be copied to a template Excel file.
I have the code working to copy each selection to the clipboard and then all rows to the Excel file. But I need assistence in figuring out how to pause the code to allow the user to make the selection and then restart the code to copy the selection to the clipboard. I am able to get the userform with toggle switch to switch states and labels when pressed. But have not figured out how to pause the VBA code to allow the user to navigate to the next section of the Word document for the next selection.
The Stakeoverflow question/answer below appears to address this requirement but I have not been able to get it to work. It appears that the code is incomplete.
Pause VBA macro, allow user to make a selection, and restart where it left off
Can someone provide example VBA code that accomplishes this?
Your assistence is much appreciated as I have been beating my head against the wall and it is starting to hurt!
There's no way in VBA to "pause" a macro. Code must run to completion... Unless there's a command for user input.
Input can be requested via the InputBox and MsgBox methods, but those block access to the document because they're modal. A UserForm, however, can be set to display as non-modal, meaning it stays on top, but doesn't block access to the document or the application features. Since you're already working with a UserForm, this can be implemented relatively easily.
In the small example below, the Continue button runs the code to perform an action on the user selection. When Done is clicked the entire code is exited and the form unloaded.
Code behind the user form
Option Explicit
Private Sub cmdContinue_Click()
Debug.Print Selection.Range.Text
End Sub
Private Sub cmdDone_Click()
Me.Hide
End Sub
Private Sub UserForm_Activate()
'Position the form near the top-left of the window
'So that the user can work with the document
Me.Top = Application.ActiveWindow.Top + 50
Me.Left = Application.ActiveWindow.Left + 50
End Sub
Code in a regular module
Option Explicit
Sub DisplayModeless()
Dim frm As frmModelessForInput
Set frm = New frmModelessForInput
frm.Show False 'Display as non-modal
Set frm = Nothing
End Sub

Why does Macro Enabled Excel Workbook kill UserForm in another Macro Enabled Excel Workbook when closed?

Scenario:
User is running a macro-enabled Excel Workbook. User clicks a link on a UserForm that launches another macro-enabled Excel Workbook that also has user forms. The second Workbook is then closed using the following code:
Private Sub btnExit_Click()
'Check if other Excel files are open before quitting the application
If Workbooks.Count = 1 Then
Application.Quit
Else
ThisWorkbook.Close
End If
End Sub
and...
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim intResponse As Integer
If MsgBox("Are you sure you would like to exit the calculator?", vbYesNo + vbQuestion) = vbNo Then
Cancel = True
End If
ThisWorkbook.Saved = True
End Sub
Upon closing of the second Workbook (ThisWorkbook.Close), the original Workbook remains open, however, the vbModeless UserForm that was previously visible has been killed. It might also be pertinent to mention that the second Workbook's forms are Modal.
If the second Workbook is closed using the Excel exit button in the upper right corner, this problem does not occur.
Does anyone know why this is happening? Is it because code execution for Excel.Application is ceased when the Workbook is closed programmatically? Could it be due to the difference in form modes? Is there a work-around other than putting a button on the original Workbook in a Sheet to re-launch the UserForm?
Many thanks for any assistance with this issue!!
CiViCChiC79
This is what is happening:
Assuming that both workbooks are in the same Excel Application, Application.Quit would close them both.
ThisWorkbook.Close will close the workbook, in which the code is present.
Thus, concerning your question - you are not closing the second workbook with ThisWorkbook.Close, but you are closing the workbook, which has the btnExit button, on which you have clicked. I guess that both the workbooks are quite similar and you are mistaken which one you are closing?
Changing the second Workbook's form containing the Exit button to vbModeless fixed the problem!!!! Yay!!!!!

unable to close opened excel workbook

I am building a excel file with commandbuttons, userforms etc. that contain links to other workbooks.
For the commandbuttons on my sheet I use the same code as for the commandbuttons in my userforms:
workbooks.open "path"
with the userform commandbuttons ater this the following is added
unload me
When I open a workbook via a userform I am unable to close it afterwards. I must activate my workbook first, then activate the opened one and then can I close it
I have tried putting "unload me" befor and after the "workbooks.open" but this doesn't change anything.
I also tried the followin, also didn't work:
unload me
dim wb as workbook
set wb = workbooks.open"pathname"
wb.activate
anyone any ideas?
Example of how it is now:
Someone needs to make a price calculation. they open the prices userform in my file. they click on the button "calculationfile". The calculationfile opens. they make there calculation and now they are finished in the calculationfile. So they want to close it by clicking on the cross. But they can't click the cross. then they switch to my file on the taskbar and then switch back to the calculation file. now they are able of clicking the cross
I dont understand why they can't click it the first time but they can click it after switching between mine and the openend workbook.
I suspect this is due to improper form handling and the "default instance" recreating itself after you unload it. If you don't create your own instance of the form before you show it, VBA will do all kinds of squirrelly things when you use it after it's unloaded.
If all you need to do is open a workbook and unload the form, *don't increment the workbook's reference count before you unload the form. Also, don't attempt to run any other code after you call Unload Me from the form. The code you posted should simply be:
Workbooks.Open "pathname"
Unload Me
Of course the calling code for the form isn't in the question, but it can likely be solved there as well.
Unload only affects a UserForm.
Try adding a reference to the open workbook and then closing it like so:
dim wb as Workbook
set wb = Workbooks.Open "pathname"
wb.activate
' do whatever with it while it's open
wb.Close
If whatever you are doing is not automated, you will need a button on your form that will set the reference to the workbook and close it once the user has completed editing.
If you define the workbooks that you open as a variable - you will be able to close them easily. Keep in mind this does not save the workbook.
Dim DataBook As Workbook
Set DataBook = Workbooks.open ("pathname")
' Do something useful with the file
DataBook.Close
It is not completely clear what you are trying to ask here, but I'll give it my best in providing you a full answer. If you are having no success with the Unload Me statement when it comes to closing a user form, try specifying the full form name in VBA. That is:
Unload UserFormName
If you are trying to close the workbook you have opened (via the user form), you can use the Workbooks.Close method:
Dim wb as Workbook
Set wb = Workbooks.Open(Filename:="C:\example.xls")
wb.Activate
'Close workbook
wb.Close
'Unload form
Unload ExampleForm
More on the use of the Unload statement can be found here:- https://msdn.microsoft.com/en-us/library/aa445829(v=vs.60).aspx
And more on the use of the Workbooks.Close statement can be found here:- https://msdn.microsoft.com/en-us/library/office/ff838613.aspx
I'm not sure what's causing the behavior you describe (inability to click the "Close" X button in the active Excel window). However your current workflow is:
User interacts with form to review/access a file
User clicks a button on the form which unloads the form
User is then expected to manually close out of the file opened in (1)
A better solution would be to remove the third step, and close the workbook from one of the form's event-handlers (UserForm_QueryClose or UserForm_Terminate). Alternatively you could add this to a CommandButton's Click event, but that's not very different than requiring the user to manually close the file.
This could be as simple as:
Private Sub UserForm_Terminate()
' should be called when form Unloads
On Error Resume Next
Workbooks.Close "filename.xlsx"
End Sub
In this manner, the file will be closed any time the user closes or otherwise unloads the userform.
OK I think I found a way around it.
Let's say I have a workbook1 which has a form called ControlPage with command button that opens up workbook2.
Private Sub CommandButton1_Click()
Dim workbook2 As Workbook
Dim workbook1name As String
workbook1name = ThisWorkbook.name
Set workbook2 = Workbooks.Open("workbook2.xlsx")
ControlPage.Hide
Workbooks(workbook1name).Activate
Workbooks("workbook2.xlsx").Activate
End Sub
So basically because 'activate' bit doesn't seem to work properly when I try to activate workbook 2 straight away, I just activate the first, and then the second one ane after another. Twisted but did the trick for me.

Code to run AFTER right click

I want to block out some of the command bar options, but the method I am currently using is a bit too restrictive. I currently use this code:
Sub Auto_Open()
Application.CommandBars.FindControl(ID:=847).Enabled = False
End Sub
Sub Auto_Close()
Application.CommandBars.FindControl(ID:=847).Enabled = True
End Sub
The problem with this is that as long as the workbook that has this code stays open no other workbook can use voided controls. I think a solution might be to use:
Private Sub Workbook_SheetBeforeRightClick(ByVal Sh As Object, ByVal Target As Range, Cancel As Boolean)
Application.CommandBars.FindControl(ID:=847).Enabled = False
End Sub
This will stop the user from using my voided controls when they right click, say to delete a sheet.
I now need a way to remove those voids as soon as they click away, so the controls are available to use in any other workbooks they may have open. Is there an event that I can use for this which isn't so common that it will make the code run every 10 seconds? I also wondered whether you can use delays in vba to run a piece of code 5 seconds after a previous piece of code?
In the workbook module in which you want to disable the command bar options enter:
Private Sub Workbook_Activate()
Application.CommandBars.FindControl(ID:=847).Enabled = False
End Sub
Private Sub Workbook_Deactivate()
Application.CommandBars.FindControl(ID:=847).Enabled = True
End Sub
Whenever you are working in the workbook the commands should be disabled. I'm not certain it will work in Excel 2007 because Application.CommandBars.FindControl(ID:=847).Caption is &Delete and Delete is still enabled on both the cell right click and tab right click.
In Excel 2007 you can disable Ribbon commands for the active workbook but it's not easy. You have to change the workbook extension to .zip then edit the .rels file in _rels folder within the zip. Change the extension back to what it was after editing and the targeted commands or groups should be disabled. Disabling the Ribbon command also disables any associated right-click commands. The kicker is that sheet add/delete commands aren't available in the Ribbon.

How do I disable and enable macros on the fly?

I would like to test an Excel VBA app I made.
However the VBA code messes around with the visibility of cells and that's a pest when editing the sheet.
Is there an option is enable and disable macro's on the fly without having to
Close the sheet
Change the macro settings
Reopen the sheet
Close the sheet
Change the macro settings.
etc.
As far as I know, you can't enable / disable macros from an opened workbook on the fly.
Yet, you shouldn't have to because macros are only triggered thanks to a user click.
The only case I would see is for the Event Procedures (Worksheet_Change or else).
You could then create procedures to activate / deactivate events and call them from buttons in your worksbook:
Sub enableEvents()
Application.EnableEvents = True
End Sub
Sub disableEvents()
Application.EnableEvents = False
End Sub
You can also try these tips from Chris Pearson website using global vars you would change depending on your needs:
Public AbortChangeEvent As Boolean
And check if afterwards:
Private Sub Worksheet_Change(ByVal Target As Range)
If AbortChangeEvent = True Then
Exit Sub
End If
'
' rest of code here
'
End Sub
To disable macros on the fly, use "Application.EnableEvents = False" via the Immediate window in the VBA editor (and "Application.EnableEvents = True" to turn them back on).
You can also hold down SHIFT when you open a document to disable macros.
As of Excel 2010* there's actually an option on the "Developer" tab which allows you to disable macros as easy as ABC. Design Mode lets you do just that!
*Maybe even earlier versions.
I often fire Macros when opening a workbook but sometimes I don't want the Macro to fire so I can work on the code. So what I put a Macro in a separate workbook that does the following:
Disables macros
Opens the workbook in question
Enables macros
Then closes the original workbook
Leaves the second workbook open
Here's the code:
Sub OpenClose()
'Opens Workbook below with Macors disabled
'After it is open Macros are enabled
'This Workbook then closes without saving changes, leaving only the workbook below open
'************************************************************
'User only needs to change the workbook name on the next line
WorkbookToOpenNoMacros = "Gaby.xlsm"
'************************************************************
Dim wb As Workbook
Set wb = Application.ThisWorkbook
Application.EnableEvents = False
Application.Workbooks.Open (ActiveWorkbook.Path & "\" & WorkbookToOpenNoMacros)
Application.EnableEvents = True
wb.Saved = True
wb.Close SaveChanges:=False
End Sub
I have Office 2013 and I found a button on the VBA window that did this for me very easily.
There's a play, pause and stop button on the toolbar. In Excel, they are actually called, Run Macro, Break and Reset.
Click the Break button (pause) and any running macros should stop running. I only tested it on one macro but seems reasonable to presume that this will work in general.
Also, I believe those buttons were there for many versions of Excel, so it's worth checking earlier versions.