我们可以使用.NET System.Windows.Forms.Time来替换Excel VBA Application

本文关键字:替换 Excel VBA Application Time Forms 可以使 NET System Windows 我们 | 更新日期: 2023-09-27 18:30:30

我们的客户

要求我们不要再使用Application.OnTime。这是我们的先决条件,对不起,它超出了我们的控制范围。

但是由于我们需要定期运行一些任务,我们需要找到一个替代计时器。我们已经尝试了System.Timers.Timer,但它在Microsoft Excel中存在一些问题。原因是Microsoft Excel 不支持多个线程,但 System.timers.timer 使用多个线程。

所以现在我们想尝试System.Windows.Forms.Timer。此计时器使用 Windows 消息泵,似乎它应该适用于 Microsoft Excel。我们可以在 C# 中使用 System.Windows.Forms.Timer ,然后定期向 VBA 引发事件。

从肯尼·科尔(Kenny Kerr)http://weblogs.asp.net/kennykerr/Rtd3 的文章来看,我们的想法似乎很好。但是有人可以更深入地挖掘并弄清楚System.Windows.Forms.Timer是如何工作的,并从基础理论中回答它为什么有效。

我们可以使用.NET System.Windows.Forms.Time来替换Excel VBA Application

如果是 VBA 应用程序,为什么要使用 .NET API? 除非您出于其他原因已经这样做了,例如它正在使用 VSTO。

不使用.NET使用Application.OnTime的替代方法是使用Win32 API(SetTimer/KillTimer)。

以下是一些代码的摘录,可帮助您入门(这不是一个完整的工作示例):

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
Private m_TimerID As Long
Private Sub StartTimer()
    m_TimerID = SetTimer(0&, 0&, 100&, AddressOf TimerProc)
End Sub
Private Sub EndTimer()
    On Error Resume Next
    KillTimer 0&, m_TimerID
End Sub
Private Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, _
    ByVal nIDEvent As Long, ByVal dwTimer As Long)
    EndTimer
    ... do your stuff here.  Call StartTimer to start the timer again if desired
End Sub

是的,之前回复中的计时器有效,是我们当前的解决方案。现在,我们要将此解决方案移至 C#。

现在我确认System.Windows.Forms.Timer 可以与 excel 一起使用,因为它以隐藏形式进行窗口消息循环。因此,线程始终与 excel 主线程相同。然后它在 Excel 中工作。

您可以使用 GetCurrentThreadId API 进行确认。