Below is my code that automatically runs the TimeStamp Macro when I open the workbook. However, it only runs if the Time is 6:45 am or later. My problem is that I am trying to get it to clear the cell contents in Columns A through D from Row 2 and on if the time is before 6:45 am and before it runs the TimeStamp macro. I tried to do it with just Column A and the debugger says that the top line is an issue. I can't seem to figure out why it is an issue though. I assume I am breaking some sort of syntax rule but I am not sure.
Private Sub Workbook_Open()
If Time > TimeSerial(6, 45, 0) Then
Call TimeStamp
Else
Sub Clear()
Dim wb3 As Workbook
Set wb3 = ThisWorkbook
With wb3.Worksheets("Avnet")
.Range("A2:A" & .Range("A2").End(xlDown).Row).ClearContents
End With
End Sub
Application.Wait "06:45:00"
Call TimeStamp
End Sub
It worked prior to me adding in the Sub Clear() section...
UPDATE:
Just tried making the Sub Clear() a separate module and using the call Clear() but that didnt work either. Here is what it looked like
The Clear () Code
Sub Clear()
Dim wb3 As Workbook
Set wb3 = ThisWorkbook
With wb3.Worksheets("Avnet")
Range("A2:A" & .Range("A2").End(xlDown).Row).ClearContents
End With
End Sub
The Part to call the Clear()
Private Sub Workbook_Open()
If Time > TimeSerial(20, 0, 0) Then
Call TimeStamp
Else
Call Clear
Application.Wait "19:35:00"
Call TimeStamp
End Sub
Declaring a sub within a sub will not work (I'm 99.9999% sure, but it's never entered my head to try this!)
Move your Sub Clear declaration so that it's after Workbook_Open, and then just call Clear from within Workbook_Open, in the same way that you call TimeStamp. (You're also missing an End If' at the end of WorkBook_open)
So your code would become:
Private Sub Workbook_Open()
If Time > TimeSerial(6, 45, 0) Then
Call TimeStamp
Else
Call Clear
Application.Wait "06:45:00"
Call TimeStamp
End If
End Sub
Sub Clear()
Dim wb3 As Workbook
Set wb3 = ThisWorkbook
With wb3.Worksheets("Avnet")
.Range("A2:A" & .Range("A2").End(xlDown).Row).ClearContents
End With
End Sub
As an aside, your Workbook_Open code can be simplified to:
Private Sub Workbook_Open()
If Time <= TimeSerial(6, 45, 0) Then
Call Clear
Application.Wait "06:45:00"
End If
Call TimeStamp
End Sub
Related
Recently I've managed to find some code regarding a timer on a userform, my problem is that I need to keep the timer running even if the userform or excel file is closed... can someone take a look at the code and provide some feedback? My userform is: optionsForm
Dim dteStart As Date, dteFinish As Date
Dim dteStopped As Date, dteElapsed As Date
Dim boolStopPressed As Boolean, boolResetPressed As Boolean
Private Sub Reset_Timer_Click()
dteStopped = 0
dteStart = 0
dteElapsed = 0
Tech_Timer = "00:00:00"
boolResetPressed = True
End Sub
Private Sub Start_Timer_Click()
Start_Timer:
dteStart = Time
boolStopPressed = False
boolResetPressed = False
Timer_Loop:
DoEvents
dteFinish = Time
dteElapsed = dteFinish - dteStart + dteStopped
If Not boolStopPressed = True Then
Tech_Timer = dteElapsed
If boolResetPressed = True Then GoTo Start_Timer
GoTo Timer_Loop
Else
Exit Sub
End If
End Sub
Private Sub Stop_Timer_Click()
boolStopPressed = True
dteStopped = dteElapsed
End Sub
Private Sub optionsForm_Initialize()
Tech_Timer = "00:00:00"
End Sub
The idea of the timer is not that it runs, but that it remembers a point in time and can give you a difference between this point and the current moment. If you ask for this difference every second, then it would look like it is running like a watch.
Something like this would be a good start. In the xl_main write the following:
Option Explicit
Dim dtime As Date
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Cells(1, 1).Value = dtime
End Sub
Private Sub Workbook_Open()
If Cells(1, 1).Value = 0 Then
dtime = Now
Else
dtime = CDate(Cells(1, 1))
End If
End Sub
You may play around it and make it better as you wish. E.g. you may find a way to reset dtime or anything similar.
"Something" needs to be running to handle the timer procedure so if you want to use VBA then Excel can't be "closed" per se, however you could make it appear closed.
An obvious option is to minimize the Excel window (before showing the userform) with the WindowState property:
Application.WindowState = xlMinimized
...or, hide the Excel window completely with the Visible property:
Application.Visible = False
...or if the issue is that you need a "fresh" copy of Excel to work in, you could do so in a new instance by holding Alt while starting Excel.
I have posted code and a downloadable example of a countdown timer that displays the time remaining on a userform semi-independent of the Excel window, using the Windows Timer API (instead of Excel's procedure), in another answer here.
That's not possible if the form is unloaded Unload optionsForm. But you can try to 'close' the form with optionsForm.hide() this only hides the form, the timer should keep running then.
The only way I see to calculate the time passed from a start time even if Excel is closed is to not save the start time in a variable dteStart but in an Excel cell.
Actually you can use a code that is placed in a module. The code is:
Option Explicit
Dim T
Sub stopTimer()
On Error Resume Next
Application.OnTime (T), Procedure:="Update", Schedule:=False
End Sub
Sub StartTimer()
T = Now + TimeValue("00:00:01")
Application.OnTime T, "Update"
End Sub
Sub Update()
UserForm1.TextBox1.Value = Format(Now - Sheets("Sheet1").Range("E11").Value,
"hh:mm:ss")
UserForm1.TextBox2.Value = Format(TimeValue("1:00:00") - (Now -
Sheets("Sheet1").Range("E11").Value), "hh:mm:ss")
Call StartTimer
End Sub
Thereafter, you can now reference it in the userform by calling it. Here is a typical example. It is
Private Sub Userform_Activate()
Sheet1.Activate
Sheets("Sheet1").Range("E11").Value = Now
Application.Run "StartTimer"
If Sheets("Sheet1").Range("K27").Value = "K29" Then
Me.CommandButton4.Caption = "Start"
Me.CommandButton2.Visible = False
End If
End Sub
So I've built this timer macro that more than one youtube person has specified how to build in this exact same way, but it still refuses to work.
Sub StartTimer()
Application.OnTime Now + TimeValue("00:00:01"), "nextTime"
End Sub
Sub nextTime()
If Sheet1.Range("I1") = 0 Then Exit Sub
End If
Range("I1").Value = Range("I1").Value - TimeValue("00:00:01")
StartTimer
End Sub
Sub StopTimer()
Application.OnTime Now + TimeValue("00:00:01"), "nextTime", , False
End Sub
The problem arises in the line of code within the StartTimer Subroutine. The nextTime method simply does not get recognized, as the Error says:
The macro may not be available in this workbook or all macros may be disabled. This is obviously not the case as all of my other macros work, and the subroutine is right there. What are your suggestions?
Move your code out of the worksheet code module and put it into a normal code module.
Alternatively, you could call it by fully qualifying it as Sheet1.nextTime (where Sheet1 needs to be the worksheet code name where the code resides), but I think it is probably better to put it into the project level code module.
You also need to remove the End If from the nextTime subroutine.
And you need to fix the StopTimer routine to pass the correct time - i.e. the time at which the next event is due to run.
Public nextRunTime As Date
Sub StartTimer()
nextRunTime = Now + TimeValue("00:00:01")
Application.OnTime nextRunTime, "nextTime"
End Sub
Sub nextTime()
If Sheet1.Range("I1") = 0 Then Exit Sub
Range("I1").Value = Range("I1").Value - TimeValue("00:00:01")
StartTimer
End Sub
Sub StopTimer()
Application.OnTime nextRunTime, "nextTime", , False
End Sub
Edit: I've managed to solve the problem below by using Application.EnableEvents = False in Workbook A to stop the Workbook_Open() code from running in Workbook B but am still stumped by the problem if anybody care to explain?
I've got Workbook A opening, editing, saving and closing Workbook B. As Workbook B is used by multiple users, I made it switch to Read-Only mode upon opening and display a pop-up message. However, when running the code from Workbook A, I want to stop the message box from opening. I used Application.OnTime to change Workbook B to Read-Only upon opening and to cancel the pending code upon saving within 10 seconds.
Problem: The code works when I open Workbook B directly and save within 10 seconds but when running a code from Workbook A to open=>edit=>save=>close Workbook B, Workbook B will open by itself even after it is closed.
After doing much research and trial and error by trying to use Public variables and Referencing VBA project, I settled on Application.OnTime using the resource below:
http://www.cpearson.com/excel/OnTime.aspx
Below is a sample of my code.
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
Call StopTimer
End Sub
Private Sub Workbook_Open()
Call StartTimer
End Sub
Public RunWhen As Double
Public Const cRunWhat = "Change_File_Access"
Public Const cRunIntervalSeconds = 15
Public DatabaseWB As Workbook
Sub StartTimer()
RunWhen = Now + TimeSerial(0, 0, cRunIntervalSeconds)
Application.OnTime EarliestTime:=RunWhen, Procedure:=cRunWhat, _
Schedule:=True
End Sub
Sub StopTimer()
MsgBox RunWhen
On Error Resume Next
Application.OnTime EarliestTime:=RunWhen, Procedure:=cRunWhat, _
Schedule:=False
End Sub
Sub Change_File_Access()
If Not Workbooks("WorkbookB.xlsm").ReadOnly Then Workbooks("WorkbookB.xlsm").ChangeFileAccess xlReadOnly
MsgBox "This file is set as Read-Only"
End Sub
Some quick testing shows the timer seems to be running within the context of the Workbook that the macro resides in - not the Workbook that you executed it from. So, you need to do one of 2 things - either quit the Excel application completely (probably not convenient) or reset the timer from the Worksheet you're running the code from.
I.e., in WorkbookA:
Dim book As Workbook
Set book = Workbooks.Open("WorkbookB.xlsm")
book.Save
Application.Run book.Name & "!StopTimer"
book.Close
The Goal: I'm trying to auto close out of workbooks for the reports I update as there are users who have them open, and forget to close them at night. I've set the auto close time to 12am.
Question 1: So I already have a couple of solutions for this problem. I found answers through a smattering of searches on google, and combined a few pieces of code to get exactly what I wanted. Now I'm wondering if it's possible to have the excel vba auto save & close in just one Module or ThisWorkbook. Essentially keeping all the code in one place.
Question 2: I know that the 1st and 2nd macro work I'm wondering which is more efficient and clean, and why?
1ST MACRO
' Insert into ThisWorkbook
Private Sub Workbook_Open()
Static SchedSave
If SchedSave <> 0 Then
Application.OnTime SchedSave, "SaveWork", , False
End If
SchedSave = TimeValue("09:29:00") ' Insert Desired time in Military
Application.OnTime SchedSave, "SaveWork", , True
End Sub
' Insert into module
Sub SaveWork()
ThisWorkbook.Save
ThisWorkbook.Close
End Sub
2ND MACRO
' Insert into 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
' Insert into Module
Sub Reset()
Static SchedSave
If SchedSave <> 0 Then
Application.OnTime SchedSave, "SaveWork", , False
End If
SchedSave = TimeValue("12:00:00") ' 12AM
Application.OnTime SchedSave, "SaveWork", , True
End Sub
Sub SaveWork()
ThisWorkbook.Save
ThisWorkbook.Close
End Sub
Also posted: http://www.mrexcel.com/forum/excel-q...ml#post3830083 (This is where I got help to get the 1st Macro to work)
I might not be a genius but nothing prevents you to put the "module-code" in "thisworkbook".
I don't see why you have to call the "Reset" Macro each time the workbook is opened, each time a worksheet is changed and... well isn't a worksheet activated as soon as you open a workbook? I'd say the 1st is the best.
EDIT: Lol I didn't see the unformatted 'insert this into thisworkbook
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