为什么在下面的VBA代码中使用对象types而不是用于variables声明的工作表types?

下面的代码让用户回到旧的工作表,如果一个Chart被激活,它会显示回来之前有多less数据点包含在Chart 。 我想知道为什么variablesSh在两个事件处理程序中定义为Object而不是Sheet 。 相同的variablesOldSheet

 Dim OldSheet As Object Private Sub Workbook_SheetDeactivate(ByVal Sh As Object) Set OldSheet = Sh End Sub Private Sub Workbook_SheetActivate(ByVal Sh As Object) Dim Msg As String If TypeName(Sh) = "Chart" Then Msg = "This chart contains " Msg = Msg & ActiveChart.SeriesCollection(1).Points.Count Msg = Msg & " data points." & vbNewLine Msg = Msg & "Click OK to return to " & OldSheet.Name MsgBox Msg OldSheet.Activate End If End Sub 

因为在Excel中没有这样的东西。

注意事件是SheetActivate ,而不是WorksheetActivate – “sheet”的概念包含几种types,除了被“激活”的能力之外没有什么共同之处。 Excel对象模型中没有工作Sheettypes – Workbook.Sheets集合包含各种types的对象, 包括 ChartWorksheet对象。

SheetActivate事件中的Sh参数必须是Object ,因为ChartWorksheet之间没有公共接口。

所以你需要做你所做的事情:validation对象的types,而不是假设你正在处理ChartWorksheet对象。

而不是使用TypeName函数和stringtypes检查,而应该使用TypeOf运算符:

 Private Sub Workbook_SheetActivate(ByVal Sh As Object) If TypeOf Sh Is Excel.Worksheet Then Debug.Print "Worksheet!" ElseIf TypeOf Sh Is Excel.Chart Then Debug.Print "Chart!" Else Debug.Print "Something else!" End If End Sub 

参数为Object允许将来的版本激活在每个Workbook对象实现的IWorkbookEvents隐藏接口中写入事件声明时无法想象的types的“表单”。

答案的简短版本是它必须声明为Object 。 事件正通过COM源接收器“触发”,并且返回一个IDispatch指针(在VBA中称为Object )给任何具有预订callback函数的东西。 ByVal Sh As Objectparameter passing给callback函数,以便事件处理程序可以确定哪个对象负责提升事件。 它在dispinterface WorkbookEvents的Exceltypes库中声明如下:

 [id(0x00000619), helpcontext(0x0007ad30)] void SheetActivate([in] IDispatch* Sh); 

即使不考虑其实现的COMpipe道,也必须声明为Object因为Sheets集合包含WorksheetChart对象,并且如果激活任一types的选项卡,则该事件将触发。 这两种types不共用一个通用接口,但它们都来源于同一个事件。 这意味着为了将源对象传递给事件处理程序,它必须作为延迟传递( IDispatch )来传递。 假设处理程序将确定传递的对象types,并根据发件人的types采取相应的操作。