Excel closing after time of user inactivity - vba

I am fairly new at VBA and have code in place that will close excel after inactivity. I am not sure what excel defines as inactivity and I couldn't pick up a pattern. If someone could explain this to me I would really appreciate it.
CODE IN THE "THIS WORKBOOK" SECTION
Option Explicit
Private Sub Workbook_SheetCalculate(ByVal Sh As Object)
ResetTimer
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
ResetTimer
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
ResetTimer
End Sub
CODE IN A STANDARD MACRO
Public CloseDownTime As Variant
Public Sub ResetTimer()
On Error Resume Next
If Not IsEmpty(CloseDownTime) Then Application.OnTime EarliestTime:=CloseDownTime, Procedure:="CloseDownFile", Schedule:=False
CloseDownTime = Now + TimeValue("00:10:00") ' hh:mm:ss
Application.OnTime CloseDownTime, "CloseDownFile"
End Sub
Public Sub CloseDownFile()
On Error Resume Next
Application.StatusBar = "Inactive File Closed: " & ThisWorkbook.Name
ThisWorkbook.Close SaveChanges:=True
End Sub

I'm not sure it matters more how Excel defines it or how your user would expect it to behave. From a user viewpoint, I think mouse movement and keypresses are what define activity. The absence of both would be heuristic indicators of inactivity.
Of course, the user could just be sitting there reading the sheet. A perfect method might be to install probes in the user's brain to detect if he's still paying attention. The exact steps to achieving this seem beyond the scope of this question.
EDIT: Based on your comment, I think you want to prevent the workbook from closing. Well, there are an infinite number of things you can do to prevent the workbook from closing. I think the simplest is to just delete the code in This Workbook.

Related

Limiting user interaction with the workbook - hide workbook / show only userform

Is it possible to get the same effect using ThisWorkbook.Application.Visible = False but only for one Workbook. I mean, I'd like to limiting user interaction only to UserForm, but I need have an access to anothers workbooks. At the moment this function cause hide workbook, but after open some another excel file - all object from userform are not available.
Private Sub Workbook_Open()
ThisWorkbook.Application.Visible = False
Starter.Show modeless
End Sub
Thanks for your support.
Please, create a form, let us say "Starter", having (at least) a button ("btExit"), copy the next code in its code module and show it. If the form in discussion already has some code in Initialize and Terminate events, please add the next code lines, too:
Option Explicit
Private Sub btExit_Click()
Unload Me
End Sub
Private Sub UserForm_Initialize()
ThisWorkbook.Windows(1).Visible = False
End Sub
Private Sub UserForm_Terminate()
ThisWorkbook.Windows(1).Visible = True
End Sub
So, you can simple use workbook Open event in this way:
Private Sub Workbook_Open()
Starter.Show vbModeless
End Sub

Calling a Sub or Function that sometimes doesn't exist

I'm trying to create a macro (in PERSONAL.XLSB) that every time a workbook is opened, it checks a condition and in if it's true (this means the workbook opened contains an specific Sub), it calls this Sub.
Option Explicit
Private WithEvents App As Application
Private Sub Workbook_Open()
Set App = Application
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
If condition Then Call Specific_Sub
End Sub
It runs fine when I open a file that contains that Sub, however, if the Sub is not in the file, the compiler returns the error “Sub or Function not defined”, naturally.
I’m trying very hard to find a way to do this and deal with the error, but On error GoTo doesn’t work because the compiler error is before the run time, so it’s not executed.
I guess I have to do this in a different way but I can’t picture how to do it, any help or ideas?
Thanks a lot!
Thanks to the answers I've discovered that the best way is to use Application.Run. To keep the code as simple as possible, I just changed the last part to look like this:
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
On Error Resume Next
If condition Then
Application.Run ("'" & ActiveWorkbook.FullName & "'!" & "Specific_Sub")
End If
End Sub
Thank you all.
I cobbled this together from a few web sites. The key is that your sub routines name is in a variable and application. run uses the variable. This gets past the compiler error you are running into
Sub SubExists()
Dim ByModule As Object
Dim ByModuleName As String
Dim BySub As String
Dim ByLine As Long
'
'Module and sub names
ByModuleName = "Module1"
BySub = "Specific_Sub"
On Error Resume Next
Set ByModule = ActiveWorkbook.VBProject.vbComponents(ByModuleName).CodeModule
ByLine = ByModule.ProcStartLine(BySub, vbext_pk_Proc)
If Err.Number = 0 Then
Application.Run BySub
End If
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
SubExists
End Sub

VBA How to save and close workbook after time of inactivity, unless userform is open?

This is my first time posting on this site, and would appreciate some help. I'm a member of the mrexcel forums, and have received a lot of help from those great people over there, but have not been able to find an answer to my question. At work, I've created a workbook that allows us to enter data into different worksheets via a userform. I'm trying to make this as user-friendly as I possibly can, to attempt to eliminate as many "user-errors" as possible. One issue I'm trying to avoid is a user forgetting to close the sheet when their shift is over, and locking everyone out because the workbook is read-only when another user has the file open. So, I have a code that will save and close the workbook after 40 minutes of inactivity. One issue this is causing (and it is a very minor issue, but one that has been brought up to me by one of my employees), is that every once in a while, coincidentally the user will be entering data into the userform right around that 40 minutes of inactivity, and the workbook will close before they had a chance to submit the data. I was wondering if anyone could help me modify my code so that when it reaches that 40 minutes of inactivity, before it saves and closes, it sees that the userform is open and cancels the action if it is. Here is the code that I've got. Thanks for any help I can get.
In Module 1:
Dim CloseTime As Date
Sub TimeSetting()
CloseTime = Now + TimeValue("00:40:00")
On Error Resume Next
Application.OnTime EarliestTime:=CloseTime, _
Procedure:="SavedAndClose", Schedule:=True
End Sub
Sub TimeStop()
On Error Resume Next
Application.OnTime EarliestTime:=CloseTime, _
Procedure:="SavedAndClose", Schedule:=False
End Sub
Sub SavedAndClose()
ActiveWorkbook.Close Savechanges:=True
End Sub
In ThisWorkbook:
Private Sub Workbook_Open()
Call TimeSetting
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call TimeStop
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Call TimeStop
Call TimeSetting
End Sub
Just call the TimeStop() sub on the Userform_Initialize() event, and then call the TimeSetting() sub when you close the userform
You can see if a userform is loaded by using this function:
Function IsUFLoaded(ByVal UFName As String) As Boolean
Dim UForm As Object
For Each UForm In VBA.UserForms
If UForm.Name = UFName Then
IsUFLoaded = True
Exit For
End If
Next
End Function
And then in SavedAndClose Sub:
Sub SavedAndClose()
' change userform_name to your userform name
If IsUFLoaded("userform_name") = False Then ActiveWorkbook.Close Savechanges:=True
End Sub
Why not, instead of doing what you're suggesting: allowing a user to accidentally leave themselves logged in to a userform which would cause the issue you're trying to avoid, you instead also reset the timer with Call TimeStop and Call TimeSetting within the change events of fields in the userform?

Auto_open & Workbook_open with Connection refresh in VBA

I have a script that refreshes my data connection to a SQL server. I need to the macro to run when the workbook is opened but for some reason it will not. I guess it has to do with the connection refresh. I tried with both Workbook_Open and Auto_Open() and neither are working. Other than the data load the only thing I am doing is filtering and copying data, nothing exotic.
Does the data refresh need permissions outside of the script, is that the problem?
Here are the first couples lines.
Sub Auto_Open()
ActiveWorkbook.Connections("Connection Name").Refresh
other stuff
end sub
You are putting the code in 'ThisWorkbook' object, right.
Private Sub Workbook_Open()
ActiveWorkbook.RefreshAll
End Sub
Private Sub Workbook_Open()
'Step 1: Use the RefreshAll method
Workbooks(ThisWorkbook.Name).RefreshAll
End Sub
user6058587 was close, but you just need to add this to ThisWorkbook:
Private Sub Workbook_Open()
'Step 1: Use the RefreshAll method
Workbooks(ThisWorkbook.Name).RefreshAll
End Sub

VBA Events: load workbook before running code using workbook_open

I want to run a VBA macro AFTER the workbook has finished opening. I tried to use workbook_open but this runs before the workbook has finished opening. This doesn't work for me as I need to loop through each sheet like so...
Private Sub Workbook_Open()
Dim ws As Worksheet
For Each ws In ActiveWorkbook.Worksheets
'do stuff on each sheet
Next ws
End Sub
Does anyone know if there is an event which runs once the workbook has finished opening? Or have any other suggestions on how I can achieve this?
I had a similar problem that I solved using Application.OnTime.
From the linked MSDN Library Article:
Schedules a procedure to be run at a specified time in the future
(either at a specific time of day or after a specific amount of time
has passed).
You could try using this method to provide the workbook with enough time to open before running the DoStuff procedure:
Private Sub Workbook_Open()
Application.OnTime Now + TimeValue("00:00:01"), "DoStuff"
End Sub
Ensure the DoStuff procedure is not in a worksheet module:
Private Sub DoStuff()
'Implementation...
End Sub
The time can be adjusted but one second was satisfactory for me.
Put your code in the Workbook_Activate event. It happens after the Open event.
Private Sub Workbook_Activate()
' Code goes here
End Sub
Try using ThisWorkbook rather than ActiveWorkbook:
Private Sub Workbook_Open()
Dim osht As Worksheet
For Each osht In ThisWorkbook.Worksheets
Debug.Print osht.Name
Next osht
End Sub