Problem showing time

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.
 
B

Bob Phillips

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)
 
K

Keith

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, _
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top