Does anyone know any VBA code that will close and save an excel file after a delay? I tried some kutools code that was supposed to close only after some idle time but it closes without checking for inactivity.
Paste in Routine Module:
Option Explicit
Const idleTime = 30 'seconds
Dim Start
Sub StartTimer()
Start = Timer
Do While Timer < Start + idleTime
DoEvents
Loop
'///////////////////////////////////////////////////////
Application.DisplayAlerts = False
Application.ScreenUpdating = False
'Step 1: Declare your variables
Dim ws As Worksheet
'Step 2: Unhide the Starting Sheet
Sheets("Sheet1").Visible = xlSheetVisible
'Step 3: Start looping through all worksheets
For Each ws In ThisWorkbook.Worksheets
'Step 4: Check each worksheet name
If ws.Name <> "Sheet1" Then
'Step 5: Hide the sheet
ws.Visible = xlVeryHidden
End If
'Step 6: Loop to next worksheet
Next ws
'Application.ScreenUpdating = True
Range("A1").Select
ThisWorkbook.Save
'Application.DisplayAlerts = True
'//////////////////////////////////////////////////////////
'Application.DisplayAlerts = False
Application.Quit
ActiveWorkbook.Close SaveChanges:=True
Application.DisplayAlerts = True
End Sub
Paste in ThisWorkbook :
Option Explicit
Private Sub Workbook_Open()
StartTimer
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
StartTimer
End Sub
Paste in Routine Module:
Sub Reset()
Static SchedSave
If SchedSave <> 0 Then
Application.OnTime SchedSave, "SaveWork", , False
End If
SchedSave = Now + TimeValue("00:10:00") '<--- Ten minutes
Application.OnTime SchedSave, "SaveWork", , True
End Sub
Sub SaveWork()
MsgBox "Run the close workbook macro here."
'ThisWorkbook.Save
'Application.Quit
'ThisWorkbook.Close
End Sub
Paste in ThisWorkbook:
Private Sub Workbook_Open()
Reset
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Reset
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Reset
End Sub
Timer will start automatically when workbook is opened. Presently set for 10 minutes (can be adjusted). Closing macro code has been disabled and presently replaced with a MsgBox notice.
Related
I have a button with a simple macro that deletes certain sheets.
I'd like to show this button only when those sheets are actually there (I can use worksheets.count because I have 2 "permanent" sheets; if > 2 then I know I have a new sheet and I want to show the button to delete it if I want to).
I think I have to use "Workbook.SheetChange event" because "Worksheet.Change event" doesn't seem to work for me in this case.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim foglio_parametri As Worksheet
Set foglio_parametri = ThisWorkbook.Worksheets("PARAMETRI") 'my main sheet where I want to show/hide the button
Application.ScreenUpdating = True
If Application.Worksheets.Count > 2 Then
foglio_parametri.CommandButton2.Visible = True
Else
foglio_parametri.CommandButton2.Visible = False
End If
End Sub
Thank you very much for your time.
I will not use your names as they are in a foreign language I do not understand .
Let's assume the button you are talking about is in a sheet with the name sheet3 which also has the codename sheet3. The button itself has the name CommandButton1. Let's further assume the certain sheets you are talking about have the names sheet4 and sheet5 then I would add the following code to the workbook module
Option Explicit
Private Sub Workbook_Open()
Sheet3.HidecmdBtn
End Sub
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
If Sh.Name = "Sheet3" Then
Sheet3.HidecmdBtn
End If
End Sub
In the worksheet module of sheet3 you have the following code
Option Explicit
Private Sub CommandButton1_Click()
' Your code goes here
' In case your code deletes the sheets you have to hide the button
HidecmdBtn
End Sub
Sub HidecmdBtn()
Dim Sh As CommandButton
' My button is located on sheet 3 and has the name "CommandButton1"
Set Sh = CommandButton1
Dim sh1Name As String
Dim sh2Name As String
sh1Name = "Sheet4"
sh2Name = "Sheet5"
If SheetExists(sh1Name) Or SheetExists(sh2Name) Then
Sh.Visible = msoTrue
Else
Sh.Visible = msoFalse
End If
End Sub
In a normal module you have
Public Function SheetExists(SheetName As String, Optional wrkBook As Workbook) As Boolean
If wrkBook Is Nothing Then
Set wrkBook = ActiveWorkbook 'or ThisWorkbook - whichever appropriate
End If
Dim obj As Object
On Error GoTo HandleError
Set obj = wrkBook.Sheets(SheetName)
SheetExists = True
Exit Function
HandleError:
SheetExists = False
End Function
I have a code that opens another workbook (source.xlsx) when I open (triggers on Workbook_Open event) a template workbook (template.xlsm).
The code:
Private Sub Workbook_Open()
Application.Screenupdating= False
Set w = workbooks
w.open filename:="link", Updatelinks:=true , readonly:=true
activewindow.visible=false
thisworkbook.activate
application.screenupdating=True
end sub
However, I want the source workbook to just run on background upon opening and close it when I close the template file.
Private sub workbook_aftersave()
Workbook("source.xlsx").Close SaveChanges:=False
End Sub
You want to use the Workbooks collection (Workbooks("source.xlsx")), rather than a Workbook object (Workbook("source.xlsx"), which will throw an error). Also, rather than trying to close it on the Workbook_AfterSave event, you could try using the Workbook_BeforeClose event:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next 'In case the Workbook is already closed
Workbooks("source.xlsx").Close SaveChanges:=False
End Sub
{EDIT} And, because I can, here's a tidier version of your Workbook_Open code too:
Private Sub Workbook_Open()
Application.ScreenUpdating = False
Dim wsSource As Workbook
Set wsSource = Workbooks.Open(Filename:="SomeDirectory\source.xlsx", UpdateLinks:=True, ReadOnly:=True) 'Change the filename to where your "source.xlsx" is stored
DoEvents 'Wait for it to finish opening
wsSource.Windows(1).Visible = False
ThisWorkbook.Activate
Application.ScreenUpdating = True
End Sub
Try using
Application.Visible = False
Place this in your Workbook_Open code on the workbook you want to hide, and then use True to bring it back to close.
I have written multiple macros that will be executed with a command button however I want my last macro to remain active after all before macros have been executed. I want Macro15 to remain active after. And for for Macro15 I want if any cell changes I want to highlight that cell with colorindex 3
Sub RunallMacros()
macro1
macro2
macro3
macro5
Macro12
Macro13
Macro14
Macro15
End Sub
Sub macro1()
ThisWorkbook.Sheets("Main").Activate
End Sub
Sub macro2()
Dim myvalue As Variant
myvalue = InputBox("Enter Safety Stock Days")
Range("R5").value = myvalue
End Sub
Sub macro5()
Dim answer As Integer
answer = MsgBox("Are There Any ICF Forms?", vbYesNo + vbQuestion, "Other Sales")
If answer = vbYes Then ICFUserForm.Show
End Sub
Sub macro3()
Dim MyAnswer1 As Variant
Dim MyAnswer2 As Variant
Dim MyAnswer3 As Variant
Dim MyAnswer4 As Variant
Dim MyAnswer5 As Variant
MyAnswer1 = InputBox("Enter Growth Current Month")
Range("m3").value = MyAnswer1
MyAnswer2 = InputBox("Enter Growth Current Month+1")
Range("n3").value = MyAnswer2
MyAnswer3 = InputBox("Enter Growth Current Month+2")
Range("o3").value = MyAnswer3
MyAnswer4 = InputBox("Enter Growth Current Month+3")
Range("p3").value = MyAnswer4
MyAnswer5 = InputBox("Enter Growth Current Month+4")
Range("q3").value = MyAnswer5
End Sub
Sub Macro12()
ActiveCell.FormulaR1C1 = "='raw data'!R[-5]C"
Range("A7").Select
Selection.AutoFill Destination:=Range("A7:A500"), Type:=xlFillDefault
End Sub
Sub Macro13()
Range("C7").Select
Selection.ClearContents
End Sub
Sub Macro14()
For Each ws In ActiveWorkbook.Worksheets
If ws.Name <> "Raw" And ws.Name <> "Main" And ws.Name <> "Calendar" Then
For Each c In ws.Range("A50:A300")
ws.Rows(c.Row).Hidden = c.value = 0
Next
End If
Next
End Sub
Sub Macro15()
If Not Intersect(Target, Range("A7:AH500")) Is Nothing Or _
Not Intersect(Target, Range("A7:AH500")) Is Nothing Then
Target.Interior.ColorIndex = 3
End If
End Sub
A macro that is "active" is doing something, i.e. it is executing code. While it is executing code, the user can't do anything. So either the macro is active or the user is active.
What you want is to respond to an event, in this case the Worksheet.Change event:
Private Sub Worksheet_Change(ByVal Target as Range)
Target.Interior.ColorIndex = 3
End Sub
See https://msdn.microsoft.com/en-us/library/office/ff839775.aspx
Great answer from Paul - try this to get it working;
Private Sub Worksheet_Change(ByVal Sh As Object, ByVal Target as Range)
Target.Interior.ColorIndex = 3
End Sub
I have come across a strange glitch in a code that I found online. if I have two different spreadsheets open, one with this code in it and another that may well have no macros at all, and i leave that one alone for the specified time (as is the time I allow for in the macro) then the spreadsheet that has the macro in closes on me and then after the given time, the other spreadsheet closes too. Why does this happen?
Module 1:
Dim DownTime As Date
Sub SetTimer()
DownTime = Now + TimeValue("00:00:20")
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 = False
Call ExampleToSaveWorkbook
With ThisWorkbook
.Saved = True
.Close
End With
End Sub
Sub ExampleToSaveWorkbook()
'Saving the Workbook
bnam = ActiveWorkbook.Name
filenm = "S:\Economics\GTAA\dailyPM\excelfiles\backups\" & bnam
ActiveWorkbook.SaveAs filenm
End Sub
ThisWorkbook
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
Why is it closing more than the 1 workbook which has the macro?
The Shutdown sub calls ExampleToSaveWorkbook which closes the active workbook.
The remainder of the Shutdown then proceeds to close the ThisWorkBook object.
How can VBA keep track of which workbooks are open?
I am writing a data mining macro that takes information from a variable number of workbooks. The user may choose what workbooks will be parsed via a userform. However, workbooks can be opened and closed while the userform is running.
So, how can my userform keep track of which workbooks are open, so that it can display them accurately.
Right now, I'm using a recursive function that calls itself with "Application.OnTime". I don't really like this solution for because it involves extra checks to see if the userform is still open, as well as having a delay because of whatever period the function is called at.
Final: Combined solution from answers and comments
userform code, requires a ListBox called WorkbookList, and a Textbox called FileTextBox
Private WithEvents App As Application
Public Sub WorkbookList_UpdateList()
WorkbookList.Clear
For Each Wb In Application.Workbooks
WorkbookList.AddItem Wb.name
Next Wb
End Sub
Private Sub WorkbookList_Change()
If WorkbookList.ListIndex = -1 Then Exit Sub
key = WorkbookList.List(WorkbookList.ListIndex)
For Each Wb In Application.Workbooks
IsWorkBookOpen Wb.path
If Wb.name = key Then FileTextbox.text = Wb.path
Next Wb
End Sub
Private Sub App_WorkbookOpen(ByVal Wb As Workbook)
WorkbookList_UpdateList
End Sub
Private Sub App_NewWorkbook(ByVal Wb As Workbook)
WorkbookList_UpdateList
End Sub
Private Sub App_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
Application.OnTime Now + TimeValue("00:00:01"), "WorkbookClosed"
End Sub
Private Sub UserForm_Initialize()
Set App = Application
WorkbookList_UpdateList
UpdatePeriodicly
End Sub
module code (put this in a vba module):
'Code From: http://www.ozgrid.com/forum/showthread.php?t=152892
Function IsUserFormLoaded(ByVal UFName As String) As Boolean
Dim UForm As Object
IsUserFormLoaded = False
For Each UForm In VBA.UserForms
If UForm.name = UFName Then
IsUserFormLoaded = True
Exit For
End If
Next
End Function
Public Sub WorkbookClosed()
If IsUserFormLoaded("InputForm") = False Then Exit Sub
InputForm.WorkbookList_UpdateList
End Sub
You can use Application Events fgor this.
E.g. see cpearson.com/excel/appevent.aspx
Private WithEvents app As Excel.Application
Sub Init()
Set app = Application 'start capturing events
End Sub
Private Sub app_NewWorkbook(ByVal Wb As Workbook)
Debug.Print "New"
End Sub
Private Sub app_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
Debug.Print "Before close: " & Wb.Name
End Sub
Private Sub app_WorkbookOpen(ByVal Wb As Workbook)
Debug.Print "Open: " & Wb.Name
End Sub
So I think that this is an interesting script and something that might be useful for the problem your trying to solve.
Public Function IsWorkBookOpen(FileName As String)
Dim ff As Long, ErrNo As Long
On Error Resume Next
ff = FreeFile()
Open FileName For Input Lock Read As #ff
Close ff
ErrNo = Err
On Error GoTo 0
Select Case ErrNo
Case 0: IsWorkBookOpen = False 'Workbook IS NOT
Case 70: IsWorkBookOpen = True 'Workbook IS open
Case Else: Error ErrNo
End Select
End Function
You can call this by doing something like this
Ret = IsWorkBookOpen("C:\test.xlsm")
If Ret = True Then 'YOUR CODE HERE