Problem showing time

  • Thread starter Thread starter keith
  • Start date Start date
K

keith

Hello,

In Excel I created a userform, with a label, and a button
control. In the userform's activate subroutine, I added
the code shown below.

When the userform is activated, it displays the time and
updates. The difficulty is that it does not update every
second. Many times it skips a second or two or three.
I'd prefer that the time be correct to the second. How
can i improve on this sub? Is there a way to make the
time display event-driven based upon the change in a
second?

thanks

Keith

Private Sub UserForm_Activate()

Dim string1 As String
Dim x As Long
Dim lastsecond
UserForm1.Caption = "Current Time"

x = 0
Do While x <> 1

string1 = DateTime.Date & " " & _
" " & DateTime.Hour(Time) & _
":" & Format(DateTime.Minute(Time), "00") & _
":" & Format(DateTime.Second(Time), "00")

If DateTime.Second(Time) <> lastsecond Then

UserForm1.Label1.Caption = string1
UserForm1.Repaint
lastsecond = DateTime.Second(Time)
End If

DoEvents

Loop

End Sub

The button control on the userform, stops the program and
unloads the form.
 
Keith,

Try This approach. Put these bits of code in separate modules

'Module1
Option Explicit

Private Declare Function GetCurrentVbaProject Lib "vba332.dll" _
Alias "EbGetExecutingProj" _
(hProject As Long) As Long

Private Declare Function GetFuncID Lib "vba332.dll" _
Alias "TipGetFunctionId" _
(ByVal hProject As Long, _
ByVal strFunctionName As String, _
ByRef strFunctionID As String) As Long

Private Declare Function GetAddr Lib "vba332.dll" _
Alias "TipGetLpfnOfFunctionId" _
(ByVal hProject As Long, _
ByVal strFunctionID As String, _
ByRef lpfnAddressOf As Long) As Long

'---------------------------------------------------------------------------
-
Public Function AddrOf(CallbackFunctionName As String) As Long
'---------------------------------------------------------------------------
-
'AddressOf operator emulator for Office97 VBA
'Authors: Ken Getz and Michael Kaplan
'---------------------------------------------------------------------------
-
Dim aResult As Long
Dim CurrentVBProject As Long
Dim strFunctionID As String
Dim AddressOfFunction As Long
Dim UnicodeFunctionName As String

'convert the name of the function to Unicode system
UnicodeFunctionName = StrConv(CallbackFunctionName, vbUnicode)

'if the current VBProjects exists...
If Not GetCurrentVbaProject(CurrentVBProject) = 0 Then
'...get the function ID of the callback function, based on its
'unicode-converted name, to ensure that it exists
aResult = GetFuncID(hProject:=CurrentVBProject, _
strFunctionName:=UnicodeFunctionName, _
strFunctionID:=strFunctionID)
'if the function exists indeed ...
If aResult = 0 Then
'...get a pointer to the callback function based on
'the strFunctionID argument of the GetFuncID function
aResult = GetAddr(hProject:=CurrentVBProject, _
strFunctionID:=strFunctionID, _
lpfnAddressOf:=AddressOfFunction)
'if we've got the pointer pass it to the result of the function
If aResult = 0 Then
AddrOf = AddressOfFunction
End If

End If

End If

End Function

'---------------------------------------------------------------------------
-
Public Function AddrOf_Callback_Routine() As Long
'---------------------------------------------------------------------------
-
'Office97 VBE does not recognise the AddressOf operator;
'however, it does not raise a compile-error ...
'---------------------------------------------------------------------------
-
AddrOf_Callback_Routine = vbaPass(AddressOf cbkRoutine)
End Function

'---------------------------------------------------------------------------
-
Private Function vbaPass(AddressOfFunction As Long) As Long
'---------------------------------------------------------------------------
-
vbaPass = AddressOfFunction
End Function


'Module2
Option Explicit

Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long

Private Declare Function SetTimer Lib "user32" _
(ByVal hWnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long

Private Declare Function KillTimer Lib "user32" _
(ByVal hWnd As Long, _
ByVal nIDEvent As Long) As Long

Public ClockView As String
Public CountDown As Long
Public timer As MSForms.Label

Private oldStatusBar
Private WindowsTimer As Long


Public Function cbkRoutine(ByVal Window_hWnd As Long, _
ByVal WindowsMessage As Long, _
ByVal EventID As Long, _
ByVal SystemTime As Long) As Long
Dim CurrentTime As String
On Error Resume Next
timer.Caption = Format(Now, "Long Time")
End Function

Sub StartClock()
timer.Caption = Format(Now, "Long Time")
fncWindowsTimer 1000, WindowsTimer '1 sec
End Sub

Sub StopClock()
fncStopWindowsTimer
End Sub

Sub RestartClock()
If ClockView = "Status Bar" Then
oldStatusBar = Application.DisplayStatusBar
Application.DisplayStatusBar = True
End If
fncWindowsTimer 1000, WindowsTimer '1 sec
End Sub

Public Function fncWindowsTimer(TimeInterval As Long, WindowsTimer As Long)
As Boolean
WindowsTimer = 0
'if Excel2000 or above use the built-in AddressOf operator to
'get a pointer to the callback function
If Val(Application.Version) > 8 Then
WindowsTimer = SetTimer(hWnd:=FindWindow("XLMAIN",
Application.Caption), _
nIDEvent:=0, _
uElapse:=TimeInterval, _
lpTimerFunc:=AddrOf_Callback_Routine)
Else 'use K.Getz & M.Kaplan function to get a pointer
WindowsTimer = SetTimer(hWnd:=FindWindow("XLMAIN",
Application.Caption), _
nIDEvent:=0, _
uElapse:=TimeInterval, _
lpTimerFunc:=AddrOf("cbkRoutine"))
End If

fncWindowsTimer = CBool(WindowsTimer)

DoEvents

End Function

Public Function fncStopWindowsTimer()
KillTimer hWnd:=FindWindow("XLMAIN", Application.Caption), _
nIDEvent:=0 'WindowsTimer
End Function

and change your activate event to just this

Private Sub UserForm_Activate()
Set timer = Me.Label1
StartClock
End Sub


There is also a StopClock function, so you can add a button to stop it.


--

HTH

Bob Phillips
... looking out across Poole Harbour to the Purbecks
(remove nothere from the email address if mailing direct)
 
Hi Bob,
Thanks very much,
Keith
-----Original Message-----
Keith,

Try This approach. Put these bits of code in separate modules

'Module1
Option Explicit

Private Declare Function GetCurrentVbaProject Lib "vba332.dll" _
Alias "EbGetExecutingProj" _
(hProject As Long) As Long

Private Declare Function GetFuncID Lib "vba332.dll" _
Alias "TipGetFunctionId" _
(ByVal hProject As Long, _
ByVal strFunctionName As String, _
ByRef strFunctionID As String) As Long

Private Declare Function GetAddr Lib "vba332.dll" _
Alias "TipGetLpfnOfFunctionId" _
(ByVal hProject As Long, _
ByVal strFunctionID As String, _
ByRef lpfnAddressOf As Long) As Long

'--------------------------------------------------------- ------------------
-
Public Function AddrOf(CallbackFunctionName As String) As Long
------------------
-
'AddressOf operator emulator for Office97 VBA
'Authors: Ken Getz and Michael Kaplan
'--------------------------------------------------------- ------------------
-
Dim aResult As Long
Dim CurrentVBProject As Long
Dim strFunctionID As String
Dim AddressOfFunction As Long
Dim UnicodeFunctionName As String

'convert the name of the function to Unicode system
UnicodeFunctionName = StrConv(CallbackFunctionName, vbUnicode)

'if the current VBProjects exists...
If Not GetCurrentVbaProject(CurrentVBProject) = 0 Then
'...get the function ID of the callback function, based on its
'unicode-converted name, to ensure that it exists
aResult = GetFuncID(hProject:=CurrentVBProject, _
strFunctionName:=UnicodeFunctionName, _
strFunctionID:=strFunctionID)
'if the function exists indeed ...
If aResult = 0 Then
'...get a pointer to the callback function based on
'the strFunctionID argument of the GetFuncID function
aResult = GetAddr (hProject:=CurrentVBProject, _
strFunctionID:=strFunctionID, _
 
Back
Top