为什么在下面的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对象模型中没有工作Sheet
types – Workbook.Sheets
集合包含各种types的对象, 包括 Chart
和Worksheet
对象。
SheetActivate
事件中的Sh
参数必须是Object
,因为Chart
和Worksheet
之间没有公共接口。
所以你需要做你所做的事情:validation对象的types,而不是假设你正在处理Chart
或Worksheet
对象。
而不是使用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 Object
parameter passing给callback函数,以便事件处理程序可以确定哪个对象负责提升事件。 它在dispinterface WorkbookEvents
的Exceltypes库中声明如下:
[id(0x00000619), helpcontext(0x0007ad30)] void SheetActivate([in] IDispatch* Sh);
即使不考虑其实现的COMpipe道,也必须声明为Object
因为Sheets
集合包含Worksheet
和Chart
对象,并且如果激活任一types的选项卡,则该事件将触发。 这两种types不共用一个通用接口,但它们都来源于同一个事件。 这意味着为了将源对象传递给事件处理程序,它必须作为延迟传递( IDispatch
)来传递。 假设处理程序将确定传递的对象types,并根据发件人的types采取相应的操作。