This question already has answers here:
Automatically close Workbook after inactivity
(2 answers)
Closed 7 years ago.
I want my WB to trigger some code after inactivity time (set by me, naturally). I could only find code to close the WB after inactivity time, but I want the code to do something else, different from closing the WB. I found this code for closing the WB:
This Workbook module:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
stop_Countdown
ThisWorkbook.Save
End Sub
Private Sub Workbook_Open()
start_Countdown
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
stop_Countdown
start_Countdown
End Sub
Private Sub Workbook_SheetCalculate(ByVal Sh As Object)
stop_Countdown
start_Countdown
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, _
ByVal Target As Excel.Range)
stop_Countdown
start_Countdown
End Sub
Regular module:
Option Explicit
Public Close_Time As Date
Sub start_Countdown()
Close_Time = Now() + TimeValue("00:00:10")
Application.OnTime Close_Time, "close_WB"
End Sub
Sub stop_Countdown()
Application.OnTime Close_Time, "close_WB", , False
End Sub
Sub close_wb()
ThisWorkbook.Close True
End Sub
In what part of the code should I introduce the events I want the WB to do, after inactivity, instead of closing the WB?
You need to make changes in the Regular module.
Instead of passing the String close_wb() in your Application.OnTime function call, you have to specify the name of the procedure containing whatever you want to perform.
Here is the code to get you started:
Option Explicit
Public Inactivity_Time As Date
Sub start_Countdown()
Inactivity_Time = Now() + TimeValue("00:00:10")
Application.OnTime Inactivity_Time, "my_procedure" ' <- Notice that I changed the name of the procedure here
End Sub
Sub stop_Countdown()
On Error Resume Next
Application.OnTime Inactivity_Time, "my_procedure", , False ' <- And here too.
On Error GoTo 0
End Sub
Sub my_procedure()
' The code to perform you event goes here
End Sub
Please check here for more details on the Application.OnTime method.
EDIT: After some test, it appears that you can't call stop_Countdown() in the Workbook_BeforeClose sub procedure: It throws an error. According to this post, in your Workbook module, you have to replace the procedure Workbook_BeforeClose with the following one:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Close_WB
End Sub
And add the following procedure:
Public Sub Close_WB()
stop_CountDown
ThisWorkbook.Close SaveChanges:=True
End Sub
Related
SOLVED
Is there any way to check if workbook is closing when the code is in workbook_deactivate procedure? so i can inform a different message to users depending on whether they are just leaving to another workbook or they are closing the file. like following
Private Sub Workbook_Deactivate()
if thisworkbook.closing then
msgbox "message1"
else
msgbox "message2"
end if
End Sub
i've searched on the net but no solution at all.
so any help would be appreciated
SOLUTION
i've thought of a trick. i'm putting the value 1 in Z1000(if it is available) in before_close event and in deactivate, i'm checking if Z1000's value. that's it.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Range("Z1000").Value = 1 'wherever is avaliable
Me.Saved = True
End Sub
Private Sub Workbook_Deactivate()
If Range("Z1000").Value = 1 Then
MsgBox "quitting"
Else
MsgBox "deactivating"
End If
End Sub
You can detect that using the BeforeClose Event
Private Sub Workbook_BeforeClose(Cancel As Boolean)
' set Cancel to true to prevent it from closing
End Sub
I got some problem with application.ontime maybe somebody knows the solution
From the beggining
Private Sub Workbook_Open()
'some code
call macro_name
end sub
sub macro_name
'some code refreshing data on form
call start_timer
end sub
dim start_time as date
Sub start_timer()
start_time = Now() + TimeValue("00:00:05")
Application.OnTime start_time, "macro_name"
End Sub
Sub end_timer()
Application.OnTime start_time, "macro_name", , False
'MsgBox "done" i put this to be sure that code is executed
End Sub
Private Sub Workbook_BeforeClose(cancel As Boolean)
'some code
call end_timer
end sub
problem is that the timer doesn't stop. If i have some other workbook open and i close the one with ontime code it starts again at scheduled time
if i put buttons on a form
Private Sub CommandButton1_Click()
start_timer
End Sub
Private Sub CommandButton2_Click()
end_timer
End Sub
everything works ok and ontime is canceled.
I solved it partly by putting the
call end_timer
on the form closing button
Private Sub Image1_Click()
end_timer
ThisWorkbook.Close
End Sub
but if workbook will be closed some other way than button ontime won't be canceled
sorry for my english i'll try to explain better if something is unclear
I am trying to create a macro that can automatically close the workbook within 5 minutes plus there will be a pop up reminder message at 4 mins 30 sec. I want the message box to be automatically closed in 10 seconds if user does not click the ok button. I am stuck at the point that the message box cannot close within 10 seconds. Most of my code are copied from the internet. Below are my codes:
In the workbook page:
Private Sub workbook_open()
Call settimer
End Sub
Private Sub workbook_beforeclose(cancel As Boolean)
Call stoptimer
End Sub
Private Sub workbook_sheetcalculate(ByVal sh As Object)
Call stoptimer
Call settimer
End Sub
Private Sub workbook_sheetselectionchange(ByVal sh As Object, _
ByVal target As Excel.Range)
Call stoptimer
Call settimer
End Sub
In the module
Dim downtime As Date
Sub settimer()
downtime = Now + TimeValue("00:01:00")
alerttime = downtime - TimeValue("00:00:50")
Application.OnTime Earliesttime:=alerttime, _
procedure:="alertuser", schedule:=True
Application.OnTime Earliesttime:=Downtime, _
procedure:="shutdown", schedule:=True
End Sub
Sub stoptimer()
On Error Resume Next
Application.OnTime Earliesttime:=downtime, _
procedure:="shutdown", schedule:=False
End Sub
Sub shutdown()
Application.DisplayAlerts = True
With ThisWorkbook
.Save = True
.Close
End With
End Sub
Sub alertuser()
Dim wsshell
Dim intText As Integer
Set wsshell = CreateObject("WScript.Shell")
intText = wsshell.Popup("log sheet will be closed in 30 seconds if there are no more inputs", 10, "reminder")
Set wsshell = Nothing
End Sub
You need to fully qualify your procedure name. It is not finding the procedure in question. You also had a typo and where missing the global variable alerttime. Try this:
Public downtime As Date
Public alerttime As Date
Private Sub workbook_open()
Call settimer
End Sub
Private Sub workbook_beforeclose(cancel As Boolean)
Call stoptimer
End Sub
Private Sub workbook_sheetcalculate(ByVal sh As Object)
Call stoptimer
Call settimer
End Sub
Private Sub workbook_sheetselectionchange(ByVal sh As Object, _
ByVal target As Excel.Range)
Call stoptimer
Call settimer
End Sub
Sub settimer()
downtime = Now + TimeValue("00:01:00")
alerttime = downtime - TimeValue("00:00:50")
'fully qualify your procedure name here and the procedure will run
Application.OnTime Earliesttime:=alerttime, _
procedure:="WorkbookName.xlsm!ThisWorkbook.alertuser", schedule:=True
'and here... also typo was here in downtime
Application.OnTime Earliesttime:=downtime, _
procedure:="WorkbookName.xlsm!ThisWorkbook.shutdown", schedule:=True
End Sub
Sub stoptimer()
On Error Resume Next
Application.OnTime Earliesttime:=downtime, _
procedure:="shutdown", schedule:=False
End Sub
Sub shutdown()
Application.DisplayAlerts = True
With ThisWorkbook
.Save = True
.Close
End With
End Sub
Sub alertuser()
Dim wsshell
Dim intText As Integer
Set wsshell = CreateObject("WScript.Shell")
intText = wsshell.Popup("log sheet will be closed in 30 seconds if there are no more inputs", 10, "reminder")
Set wsshell = Nothing
End Sub
You could use a userform (which you Insert into your project in the VBA editor) which looks something like this:
In the properties window I changed the forms name to formReminder to make it easier to refer to in other modules. Then, in the userform's code window I put:
Private Running As Boolean
Private Sub CommandButton1_Click()
Running = False
End Sub
Private Sub UserForm_Activate()
Dim start As Single
start = Timer
Running = True
Do While Running And Timer < start + 10
DoEvents
Loop
Unload Me
End Sub
Private Sub UserForm_Click()
Running = False
End Sub
When you run the line formReminder.Show anywhere else in the code (e.g. -- in place of where you create the popup) the form will display and show for 10 seconds (or less if you click anywhere on it) and then disappear.
While it displays it will look like this:
Thanks, John Coleman for your answer. It led me to a solution I've wanted for a long time. I took your code and converted it into a generic function that accepts parameters for the message and the number of seconds to wait.
Sub MsgBoxTimerTest()
' Test the Message box with a timer form
Dim vReturn As Variant
vReturn = MsgBoxTimerCall("MessageBox that Dissappears after n Seconds", "Hello World!", 3)
End Sub
' **************************************************************************
Function MsgBoxTimerCall(strCaption As String, strMessage As String, intSeconds As Integer)
' Show a messagebox for a while
' https://stackoverflow.com/questions/37281840/automatic-close-excel-workbook-with-a-pop-up-message
' 2016-06-21
TimerSeconds = intSeconds
msgBoxTimerForm.Caption = strCaption
msgBoxTimerForm.TextBox1.Value = strMessage
msgBoxTimerForm.Show
End Function
' **************************************************************************
' **************************************************************************
Insert this code in the form
' **************************************************************************
Private Running As Boolean
Private Sub CommandButton1_Click()
MsgBox "Yo!"
Running = False
End Sub
Private Sub UserForm_Activate()
Dim start As Single
start = Timer
Running = True
Do While Running And Timer < start + TimerSeconds
DoEvents
Loop
Unload Me
End Sub
Private Sub UserForm_Click()
Running = False
End Sub
I have VBA code in the Sheet1 module and I want to call a sub procedure in that Sheet1 module when the workbook open so I do:
Private Sub Workbook_Open()
Call MyMacro
End Sub
behind SHeet1 I have
Public Sub MyMacro()
........
End Sub
When the workbook opens I get the error:
sub or function not defined "call GetReutersData"
How can I call MyMacro from the Open() event?
I need to have the MyMacro code in the sheet1 module just becuase that's the way it has to be. I cannot create a new module.
Private Sub Workbook_Open()
sheet1.MyMacro
End Sub
Please try this
Write the below code in Thisworkbook
Private Sub Workbook_Open()
Call Sheet1.MyMacro
End Sub
'----- Sheet 1 Code ---
Public Function MyMacro()
MsgBox "hi"
End Function
Is Absolutely Working on My system
I have two command buttons (cmd1 and cmd2) on userform1, when clicked each show the same userform (userform2). Within the initialize or load sub is it possible to determine which command button was clicked on userform1 and therefore show the form differently? I imagine the code in either the initialize or load sub on userform2 to have the following skeleton:
if (cmd1 was clicked)
' do stuff relating to 1
elseif (cmd2 was clicked)
' do stuff relating to 2
else
' error handling
End if
The respective "stuff" could be moved into the event handler for cmd1 and cmd2 however, if the method described above can be used it will be a lot simpler and cleaner.
Use a Public Variable in UserForm1 and then test it in UserForm2_Initialize Event.
Something like this in UserForm1:
Public whatsclicked As String
Private Sub CommandButton1_Click()
whatsclicked = "CommandButton1"
UserForm2.Show
End Sub
Private Sub CommandButton2_Click()
whatsclicked = "CommandButton2"
UserForm2.Show
End Sub
And then in UserForm2:
Private Sub UserForm_Initialize()
Select Case UserForm1.whatsclicked
Case "CommandButton1": MsgBox "CommandButton1 loaded form."
Case "CommandButton2": MsgBox "CommandButton2 loaded form."
Case Else 'Do something else
End Select
End Sub
you can do it also without public variable.
i won't show an example where you can simply write something in a cell or hidden sheet, instead i just pass the wanted info directly .
this time whatsclicked is the name of a label in userform2,
in userform1, before calling userform2:
Private Sub CommandButton1_Click()
load UserForm2
with UserForm2
.whatsclicked.caption= "CommandButton1"
.Show
end with
End Sub
Private Sub CommandButton2_Click()
load UserForm2
with UserForm2
.whatsclicked.caption= "CommandButton2"
.Show
end with
End Sub
Of course, you will have to hide the text of whatsclicked to the user (same color as font or background...)
You can use ActiveControl for this as when you click a control it becomes active/focussed:
Private Sub CommandButton1_Click()
Debug.Print Me.ActiveControl.Name
End Sub
Private Sub CommandButton2_Click()
Debug.Print Me.ActiveControl.Name
End Sub
So more in line with your example:
Private Sub CommandButton1_Click()
Call DoStuff
End Sub
Private Sub CommandButton2_Click()
Call DoStuff
End Sub
Private Sub DoStuff()
select case Me.ActiveControl.Name
case "CommandButton1"
' do stuff relating to 1
case "CommandButton2"
' do stuff relating to 2
case else
'error etc.
end select
End Sub