我的想法是使用 Workbook_SheetSelectionChange 事件来监控是否选择了具有 HYPERLINK 公式的单元格,结果非常好。
我的代码的第一次修订:
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Dim MacroName As String
If Target.Cells.Count > 1 Then Exit Sub
If Target.Formula Like "=HYPERLINK(LEFT(""|""*""|"",*),*)" Then
MacroName = Split(Target.Formula, """|""")(1)
MacroName = VBA.Trim(Replace(MacroName, "&", ""))
MacroName = Sh.Evaluate(MacroName)
Application.Run Macro
End If
End Sub
它需要有一个具有以下公式的单元格:
=HYPERLINK(LEFT("|" & A1 & "|", 0), "Run Macro in A18") 其中单元格 A1 包含我要运行的某个宏的名称。宏的名称也可以硬连线在公式中。
注意:需要 LEFT(..., 0) 部分,因此在单击超链接时,超链接的地址将显示为空。否则它会因为找不到目标而弹出错误提示。
不幸的是,当使用返回键、制表键或箭头键选择单元格时,SelectionChange 事件也会触发。要过滤掉这些,您将需要以下 API 调用:
Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vkey As Integer) As Boolean
此函数检查在调用它的那一刻是否按下了某个键。
来源是这个未解决的问题:How to run code when clicking a cell?
上面代码的下一个演变现在看起来像这样:
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If GetAsyncKeyState(vbKeyTab) _
Or GetAsyncKeyState(vbKeyReturn) _
Or GetAsyncKeyState(vbKeyDown) _
Or GetAsyncKeyState(vbKeyUp) _
Or GetAsyncKeyState(vbKeyLeft) _
Or GetAsyncKeyState(vbKeyRight) _
Or Target.Cells.Count > 1 _
Or VBA.TypeName(Sh) <> "Worksheet" _
Then Exit Sub
Dim Macro As String
If Target.Formula Like "=HYPERLINK(LEFT(""|""*""|"",*),*)" Then
Macro = Split(Target.Formula, """|""")(1)
Macro = VBA.Trim(Replace(Macro, "&", ""))
Macro = Sh.Evaluate(Macro)
Application.Run Macro
End If
End Sub
现在这将过滤掉所有由键盘命令完成的选择更改。
然而,还有一步要采取,因为我必须注意到,在更改超链接上方或左侧的单元格并按回车键或制表键时似乎存在缺陷。由于某种原因,GetAsyncKeyState 将为两个键返回 false,因此我的代码将继续运行。
所以对于这些情况,我不得不创造一些肮脏的工作。您将需要 Workbook_SheetChange 事件来设置一个临时禁用 Workbook_SheetSelectionChange 事件的开关。
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
RecentSheetChange = True
Application.OnTime VBA.DateAdd("s", 0.1, Now), "ResetRecentSheetChange"
End Sub
'Code inside a new module:
Option Explicit
Option Private Module
Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vkey As Integer) As Boolean
Public RecentSheetChange As Boolean
Private Sub ResetRecentSheetChange()
RecentSheetChange = False
End Sub
ThisWorkbook 中的最终代码现在如下所示:
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If GetAsyncKeyState(vbKeyTab) _
Or GetAsyncKeyState(vbKeyReturn) _
Or GetAsyncKeyState(vbKeyDown) _
Or GetAsyncKeyState(vbKeyUp) _
Or GetAsyncKeyState(vbKeyLeft) _
Or GetAsyncKeyState(vbKeyRight) _
Or Target.Cells.Count > 1 _
Or VBA.TypeName(Sh) <> "Worksheet" _
Or RecentSheetChange _
Then Exit Sub
Dim Macro As String
If Target.Formula Like "=HYPERLINK(LEFT(""|""*""|"",*),*)" Then
Macro = Split(Target.Formula, """|""")(1)
Macro = VBA.Trim(Replace(Macro, "&", ""))
Macro = Sh.Evaluate(Macro)
Application.Run Macro
End If
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
RecentSheetChange = True
Application.OnTime VBA.DateAdd("s", 0.1, Now), "ResetRecentSheetChange"
End Sub
向超链接添加参数特征只是从这里迈出的一小步。
你的想法?