gpt4 book ai didi

excel - 如何在 VBA 中制作安全的 API 计时器?

转载 作者:行者123 更新时间:2023-12-01 19:32:40 24 4
gpt4 key购买 nike

我在各个地方读到 API 计时器在 VBA 中存在风险,如果在计时器运行时编辑单元格,则会导致 Excel 崩溃。

此代码来自 http://optionexplicitvba.wordpress.com Jordan Goldmeier 写的似乎没有这个问题。它使用计时器淡化弹出窗口,当它淡化时,我可以单击并在单元格和编辑栏中输入文本。

API 计时器何时安全,何时不安全?有没有具体帮助我理解的原则? 崩溃的机制是什么:究竟发生了什么让 Excel 崩溃?

Option Explicit
Public Declare Function SetTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long

Public Declare Function KillTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long) As Long

Public TimerID As Long
Public TimerSeconds As Single
Public bTimerEnabled As Boolean
Public iCounter As Integer
Public bComplete As Boolean

Public EventType As Integer

Public Sub Reset()
With Sheet1.Shapes("MyLabel")
.Fill.Transparency = 0
.Line.Transparency = 0
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(0, 0, 0)
End With
Sheet1.Shapes("MyLabel").Visible = msoTrue
End Sub

Sub StartTimer()
iCounter = 1
Reset
TimerID = SetTimer(0&, 0&, 0.05 * 1000&, AddressOf TimerProc)
End Sub

Sub EndTimer()
KillTimer 0&, TimerID
bTimerEnabled = False
bComplete = True
End Sub

Sub TimerProc(ByVal HWnd As Long, ByVal uMsg As Long, _
ByVal nIDEvent As Long, ByVal dwTimer As Long)

On Error Resume Next

Debug.Print iCounter
If iCounter > 50 Then
With Sheet1.Shapes("MyLabel")
.Fill.Transparency = (iCounter - 50) / 50
.Line.Transparency = (iCounter - 50) / 50
.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = _
RGB((iCounter - 50) / 50 * 224, _
(iCounter - 50) / 50 * 224, _
(iCounter - 50) / 50 * 224)
End With
End If

If iCounter > 100 Then
Sheet1.Shapes("MyLabel").Visible = msoFalse
EndTimer
End If

iCounter = iCounter + 1
End Sub

Public Function ShowPopup(index As Integer)

Sheet1.Range("Hotzone.Index").Value = index

iCounter = 1

If bTimerEnabled = False Then
StartTimer
bTimerEnabled = True
Reset
Else
Reset
End If

With Sheet1.Shapes("MyLabel")
.Left = Sheet1.Range("Hotzones").Cells(index, 1).Left + _
Sheet1.Range("Hotzones").Cells(index, 1).Width
.Top = Sheet1.Range("Hotzones").Cells(index, 1).Top - _
(.Height / 2)
End With
Sheet1.Range("a4:a6").Cells(index, 1).Value = index

End Function

最佳答案

@酷蓝:崩溃的机制是什么:究竟发生了什么让 Excel 崩溃?

我可以给你扩展 Siddarth Rout 的答案,但不是完整的解释。

API 调用不是 VBA:它们存在于 VBA 的错误处理程序之外,当出现问题时,它们要么什么都不做,要么调用内存中不存在的资源,或者尝试读取(或写入!)外部内存Excel.exe 的指定内存空间

发生这种情况时,操作系统将介入并关闭您的应用程序。我们曾经将此称为“一般保护故障”,这仍然是对该过程的有用描述。

现在了解一些细节。

当你在 VBA 中调用一个函数时,你只需写下名字——我们称之为“CheckMyFile()”——这就是你在 VBA 中需要知道的全部内容。如果没有调用 'CheckMyFile' 的东西,或者它被声明在你的调用看不到它的地方,编译器或运行时引擎将以断点的形式引发错误,或者在编译和运行之前发出警告。

在幕后,有一个与字符串 'CheckMyFile' 相关联的数字地址:我正在简化一点,但我们将该地址称为 。函数指针 - 跟随那个地址,我们会到达一个结构化的内存块,它存储函数参数的定义、存储值的空间,以及将这些参数引导到为执行 VBA 并将值返回到创建的函数结构中的地址函数输出的地址。

事情可能会出错,VBA 做了很多工作来确保所有这些在出错时都能优雅地折叠起来。

如果您将该函数指针指向不是 VBA 的东西 - 外部应用程序或(例如) API 定时器调用 - 你的函数仍然可以被调用,它仍然可以运行,一切都会正常工作。

当您将函数指针传递给 API 时,我们将此称为“回调”,因为您调用它的计时器函数,它会回调您。

但最好在那个指针后面有一个有效的函数。

如果没有,外部应用程序将调用它自己的错误处理程序,它们不会像 VBA 那样宽容。

如果 Excel 和 VBA 处于“忙碌”状态或在尝试使用该函数指针时不可用,它可能会挂断调用并且什么也不做:你可能很幸运,只有一次。但它可能会引起操作系统对 Excel.exe 进程的愤怒。

如果回调导致错误,并且您的代码未处理该错误,则 VBA 将向调用者提出错误 - 而且,由于调用者不是 VBA,它可能无法处理:和它会向操作系统寻求“帮助”。

如果是 API 调用,它是为假定已在调用代码中放置错误处理和应急管理的开发人员编写的。

这些假设是:

  • 该指针后面肯定有一个有效的函数;
  • 调用时肯定可用;
  • ...而且它不会给调用者带来任何错误。

  • 对于 API 回调,调用者是操作系统,它对检测到错误的响应将是关闭您。

    所以这是一个非常简单的过程大纲——“为什么”而不是“什么”解释。

    完整的解释,没有过度简化,适用于 C++ 开发人员。如果你真的想深入了解答案,你必须学会​​用指针编程;您必须熟悉内存分配、异常、错误指针的后果以及操作系统用于管理正在运行的应用程序和检测无效操作的机制的概念和实践。

    VBA 的存在是为了保护您免受这些知识的影响并简化编写应用程序的任务。

    关于excel - 如何在 VBA 中制作安全的 API 计时器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20269844/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com