How can I tell which workbook triggered an event? - vba

I have a BeforeClose event in a workbook, however if the user closes the workbook when it is not the active workbook, e.g. from the taskbar, the script executes on the wrong workbook.
Is there a way to tell which workbook triggered the event and reference that workbook rather than ActiveWorkbook?
Private Sub Workbook_BeforeClose(Cancel As Boolean)
' Replaces default Save message box with custom one
' that includes request stats, warnings, and errors.
If Not ActiveWorkbook.Saved Then
UF_Stats.Show
If Not GlobalVariables.bAllowClose Then Cancel = True
End If
End Sub

Use ThisWorkbook instead of ActiveWorkbook – Vincent G

Related

Running vba code whenever a workbook is opened

I'm writing vba which manipulates data within a worksheet however I'm trying to make it run whenever a workbook is opened.
The problem I'm having is that due to the workbook (that the code needs to run on) is different/new every time, I need the auto_open code to be within a personal macro workbook.
Sub Auto_Open()
Dim bookname As String
Dim checkbook As String
Dim Workbook As Workbook
For Each Workbook In Application.Workbooks
bookname = Workbook.Name
checkbook = Left(bookname, 3)
If checkbook = "EDN" Then
Data_generator
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
Application.Quit
Else
End If
Next Workbook
End Sub
When this code runs it checks all open workbooks and sees if the first 3 letters of it are 'EDN', if it is then run the public sub called 'Data_generator', save it and quit. If it isn't check the next open workbook, etc.
When a file is opened from windows explorer, excel launches (with both the desired workbook and the personal macro workbook) however because excel opens the personal macro workbook first and runs the code before opening the desired workbook it doesn't find a workbook called 'EDN'.
If the above code is ran after both workbooks have opened then the code works as intended and cycles through each open workbook to see if there's one called 'EDN' (this was proved by putting a messagebox after the 'then' and running the code), if so run the sub.
I've proved this by putting a messagebox after the 'else', when this is done it displays the messagebox with the workbook I want, not open. After the message box is cleared, the workbook then opens.
Is there any way to make the desired workbook open first or any other work around for this?
You can create an Add-in that runs whenever a workbook is open
https://msdn.microsoft.com/en-us/library/office/gg597509(v=office.14).aspx
this tool may help to create the Add in http://www.andypope.info/vba/ribboneditor.htm
You should be able to use the Application.OnWindow event to trigger a macro when a file is opened or closed.
In ThisWorkbook
Private Sub Workbook_Open()
Call StartTracking
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call StopTracking
End Sub
In a Module
Function StartTracking()
Application.OnWindow = "AutoRunOnWindowChange"
End Function
Function StopTracking()
Application.OnWindow = ""
End Function
Function AutoRunOnWindowChange()
If Left(ActiveWorkbook.Name, 3) = "EDN" Then
Call Data_generator
Application.DisplayAlerts = False
ThisWorkbook.Save
Application.DisplayAlerts = True
Application.Quit
End If
End Function

Command button to return user back to source workbook

We have a userform that pops-up and remains on top of all applications.
Since users are always working on multiple workbooks and applications, I want a button on the userform. On clicking this button the users should be returned to the workbook from where the userform is activated.
Let's say the userform is activated from Book1. On clicking the button, users should be returned to book1.
I'm just an excel beginner. Any help will be appreciated
Something like this should work in the code for the userform:
Public wbSource As Workbook
Private Sub CommandButton1_Click()
wbSource.Activate
End Sub
Private Sub UserForm_Initialize()
Set wbSource = ThisWorkbook
End Sub

Make a sheet act like a button

I want the sheet Administrator to act like a button but I don't want to go to the actual sheet.
It should open up an UserForm and stay on the active sheet if click on Administrator.
You can create a public variable CurrentSheet, initialize it to ActiveSheet in the Workbook_Open event and then in the workbook's SheetActivate event either update the value of CurrentSheet or switch back to the previous current sheet and show the user form. Something like (in the Workbook code sheet):
Public CurrentSheet As Worksheet
Private Sub Workbook_Open()
Set CurrentSheet = ActiveSheet
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If Sh.Name = "Administrator" Then
CurrentSheet.Activate
UserForm1.Show
Else
Set CurrentSheet = Sh
End If
End Sub
On Edit: To be safe you can also add the following code. This adds a layer of protection if something causes your project to reset after the Workbook_Open event. In the original code I was able to generate a crash when I purposely reset the project before activating Administrator.
Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)
Set CurrentSheet = Sh
End Sub
This might render the code in Workbook_Open redundant, but personally I would keep it in since I don't like the idea of having uninitialized global variables, even if they will be initialized before I use them. Also -- if the workbook opens in Administrator (which might be some error condition) this will guarantee that CurrentSheet has a value.

automatically close excel userform when change sheet

I have a userform that automatically appears when a new sheet is created from a pivot table drilldown. I am trying to figure out how to have this userform automically close if the user navigates to any other sheet in the workbook.
You can use the SheetActivate event of the Workbook object to check the name of the worksheet that is active and take action accordingly. For example:
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If Sh.Name = "Sheet1" And UserForm1.Visible Then
Unload UserForm1
End If
End Sub
This event is available in the ThisWorkbook module of your Excel Workbook. I believe your UserForm will need to be Modeless for users to be able to change sheets while the form is visible.
You can read about the Workbook.SheetActivate Event here.

Where to cancel Application.OnTime in VBA

Using VBA in Excel 2003, I'm trying to cancel an Application.OnTime event using the following code:
Application.OnTime EarliestTime:=varNextRunTime, Procedure:="SomeMethod", Schedule:=False
where varNextRunTime is a global variable containing the next time it is due to run. This code runs in the Workbook_BeforeClose event handler so is always run when the workbook is closed, which is my intention.
However, if the user tries to close the workbook, but changes their mind and hits the cancel button when prompted to Save (Yes, No, Cancel), the Application.OnTime event is still cancelled. BeforeClose is always run before they decide to hit cancel, so has anyone got any ideas how I can only cancel the Application.OnTime event when the workbook is closed?
Here's some ideas
http://www.dailydoseofexcel.com/archives/2004/06/16/beforeclose-vs-beforereallyclose/
Check the Saved property of the Workbook in your event handler. If the workbook is unsaved then display your own dialog to find out if the users wants to save changes, not save changes or cancel.
Here's some rough code. Obviously uncomment the line which deals with the Application.OnTime part and change the MsgBox title to something suitable
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim response As Integer
If Not (Me.Saved) Then
response = MsgBox("Do you want to save changes to '" & Me.Name & "'?", vbYesNoCancel, "put title here")
If (response = vbCancel) Then
Cancel = True
ElseIf (response = vbYes) Then
Me.Save
End If
End If
If Not (Cancel) Then
' Application.OnTime EarliestTime:=varNextRunTime, Procedure:="SomeMethod", Schedule:=False
End If
End Sub
Investigate using:
Application.Quit
If you find this command results in the Excel program remaining open although the document has closed, you may want to follow with
ActiveWorkbook.Close False
I'm not in position to test this or give more insights, unfortunately.
A bit late to the show but here is a simple solution that I've come across (and tested):
If a user deactivates the workbook by closing it, the workbook will still remain the ActiveWorkbook when the Workbook_WindowDeactivate event fires. If the user deactivates the workbook by switching to another workbook, then the new workbook will become the ActiveWorkbook by the time Workbook_WindowDeactivate fires. You can use this behavior to determine the action that caused the event to fire:
Private Sub Workbook_WindowDeactivate(ByVal Wn As Window)
If Application.ActiveWorkbook.Name = Me.Name Then
'Your code here
End If
End Sub