如何在 Microsoft 脚本控件中实现事件?
How to Implement An Event in Microsoft Script Control?
我在 MSScriptControl 上阅读的所有文档都说它可以响应添加到它的对象的事件。
the script control allows you to write script that will automatically
fire when an event on an object occurs.
https://msdn.microsoft.com/en-us/library/ms974586.aspx
the ScriptControl will be able to sink events generated by objects
added using the AddObject method.
http://flylib.com/books/en/1.492.1.154/1/
但我没有成功。我假设这意味着当添加的对象引发它的事件时,ScriptControl 中的代码将被触发。我无法得到任何工作。
寻找将 any 对象添加到 ScriptControl 并处理该控件触发的事件的示例代码。不关心对象是自定义 class、窗体、控件还是内置 Excel 对象(如 Worksheet)。
运行在 Win Server 2008 64 位上安装 Office 2010 32 位。
对其他方法持开放态度,例如 WSH,但 Tushar Mehta 在这里没有成功 http://dailydoseofexcel.com/archives/2009/08/19/using-vbscript-to-monitor-office-eventsor-not/
我已成功将 Excel Application 对象添加到 ScriptControl,并在 Excel Application 对象上执行了代码:
这没问题:
Function TestProc()
Dim oScriptCtl As New MSScriptControl.ScriptControl
With oScriptCtl
' init
.Language = "VBScript"
.AllowUI = True
' add Excel application object
.AddObject "app", Application, True
' add procedure
Dim sCode As String
sCode = "Sub TestProc : MsgBox ""hi"" : End Sub"
.AddCode sCode
' run procedure. Msgbox displays.
.Run "TestProc"
End With
' cleanup
Set oScriptCtl = Nothing
End Function
失败:
在这个测试中,m_oScriptCtl 是一个模块范围的变量。当我点击表格时没有任何反应:
Function TestForm()
Set m_oScriptCtl = New MSScriptControl.ScriptControl
With m_oScriptCtl
' init
.Language = "VBScript"
.AllowUI = True
MyForm.Show False
.AddObject "app", Application, True
.AddObject "frm", MyForm, True
.State = Connected
Dim sCode As String
sCode = "Sub frm_Click(): MsgBox Chr(14): End Sub"
.AddCode sCode
End With
End Function
下一个在 .AddCode 上报告以下错误:
Expected ')'
Function TestSheet()
Set m_oScriptCtl = New MSScriptControl.ScriptControl
With m_oScriptCtl
' init
.Language = "VBScript"
.AllowUI = True
.AddObject "app", Application, True
.AddObject "sheet", Sheet2, True
.State = Connected
Dim sCode As String
sCode = "Private Sub sheet_Change(ByVal Target As Range): MsgBox Target: End Sub"
.AddCode sCode
End With
End Function
在接下来的测试中,MyClass定义为:
Public Event MyEvent()
Public Sub TestEvent()
RaiseEvent MyEvent
End Sub
但以下报告 "object does not support property or method" .运行。所以在这种情况下,失败的不是事件——我只是不能 运行 class 中的方法。
Function TestClassEvent()
Set oScriptCtl = New MSScriptControl.ScriptControl
Dim oClass As New MyClass
With oScriptCtl
' init
.Language = "VBScript"
.AllowUI = True
' add objects
.AddObject "app", Application, True
.AddObject "oClass", oClass, True
.State = Connected
' add code
Dim sCode As String
sCode = "Sub oClass_MyEvent() : MsgBox vbNullString : End Sub"
.AddCode sCode
.Run "oClass.TestEvent"
End With
' cleanup
Set oScriptCtl = Nothing
End Function
线索:
有人发帖:
If you totally fail to sink your events, try calling
'ScriptControl1.Modules("Global").CodeObject.Name_Of_Your_Event(ParameterList)'
http://computer-programming-forum.com/59-vbscript/4b059f9f6eacfaf0.htm
-- 但我不清楚该解决方法:事件过程不应该是 "called" 明确的,它们应该只是触发。以下几行都给出 "Method or data member not found",在上面的 TestClassEvent
示例中:
m_oScriptCtl.Modules("Global").CodeObject.MyEvent
m_oScriptCtl.Modules("Global").CodeObject.TestEvent
我没有测试以下内容,因为我不太确定如何:
the script control can't handle events from a class in the same
project as the application it's being hosted in
https://diigo.com/08we68
不确定以下是否相关,不太明白:
http://www.programmersheaven.com/discussion/79452/me-activecontrol-and-events
让它起作用的关键是:必须在listener中设置event-firing-object-class 在 之后将两者都添加到脚本控件——而不是之前。意思是,这一行必须在 SC:
内部执行
Set oListener.EventFiringObject = oEventFiringObject
这是一个在脚本控件内的对象之间触发和响应事件的工作示例。
在这个例子中:
- 我演示了 2 种事件触发对象:自定义 class 和工作表。
- 自定义 class 在添加到脚本控件 ("sc") 之前实例化。
- 我在自定义 sc 对象中调用了一个方法。
设置演示
- 开始一个新项目(即,在 Excel 中添加一个新的工作簿)。
- 在您的 VB IDE 中,添加对 Microsoft 脚本控件的引用。
- 创建以下 VB 个组件:
代码
Class clsSheetListener
:
Public WithEvents oSht As Worksheet
Private Sub oSht_Change(ByVal Target As Range)
' show changed cell
MsgBox "Sheet Listener" & vbCrLf & "Changed: " & Target.Address _
& vbCrLf & Target.Cells(1).Value2
End Sub
Class clsEventClass
:
Public Event MyEvent(sCaller As String)
Public Sub Raise_MyEvent(sCaller As String)
RaiseEvent MyEvent(sCaller)
End Sub
Class clsClassListener
:
Public WithEvents m_oEventClass As clsEventClass
Private Sub m_oEventClass_MyEvent(sCaller As String)
' show my execution-scope
MsgBox "Class Listener, " & sCaller & " caller"
End Sub
模块 Module1
:
Function Main()
' init scriptcontrol
Set m_oScriptCtl = Nothing
Set m_oScriptCtl = New MSScriptControl.ScriptControl
With m_oScriptCtl
.Language = "VBScript"
.AllowUI = True
' add Excel application object, needed for all Excel methods in script-control
.AddObject "sc_Application", Application, True
' add Sheet2 to the sc
' code executed in sc refers to objects by name, as defined in .AddObject
.AddObject "sc_oSheet", Sheet2, True
' init sheet event-listener, and add to sc
Dim oSheetListener As New clsSheetistener
.AddObject "sc_oSheetListener", oSheetListener, True
' register the sheet-object with its listener in the scriptcontrol
' so the listener can hear the sheet's events
.ExecuteStatement "Set sc_oSheetListener.oSht = sc_oSheet"
' init custom event-firing class object, and add to sc
Dim oEventClass As New clsEventClass
.AddObject "sc_oEventClass", oEventClass, True
' init class-event listener, and add to sc
Dim oClassListener As New clsClassListener
.AddObject "sc_oClassListener", oClassListener, True
' register event-firing object with its listener inside the Script Control
' so the listener can hear the object's events
.ExecuteStatement "Set sc_oClassListener.m_oEventClass = sc_oEventClass"
' cause event to be raised.
' Call from local context, then sc-context.
' it's the same object instance in both cases
oEventClass.Raise_MyEvent "Local"
.ExecuteStatement "sc_oEventClass.Raise_MyEvent ""SC"""
End With
End Function
测试
逐步完成 Main()
。您会看到 Raise_MyEvent
在 clsEventClass
中触发 MyEvent
时,clsClassListener
使用消息框响应事件。
现在切换到Excel前端,在Sheet2的单元格中输入一个值。您会看到 clsSheetListener
使用消息框响应 Change
事件。
我在 MSScriptControl 上阅读的所有文档都说它可以响应添加到它的对象的事件。
the script control allows you to write script that will automatically fire when an event on an object occurs. https://msdn.microsoft.com/en-us/library/ms974586.aspx
the ScriptControl will be able to sink events generated by objects added using the AddObject method. http://flylib.com/books/en/1.492.1.154/1/
但我没有成功。我假设这意味着当添加的对象引发它的事件时,ScriptControl 中的代码将被触发。我无法得到任何工作。
寻找将 any 对象添加到 ScriptControl 并处理该控件触发的事件的示例代码。不关心对象是自定义 class、窗体、控件还是内置 Excel 对象(如 Worksheet)。
运行在 Win Server 2008 64 位上安装 Office 2010 32 位。
对其他方法持开放态度,例如 WSH,但 Tushar Mehta 在这里没有成功 http://dailydoseofexcel.com/archives/2009/08/19/using-vbscript-to-monitor-office-eventsor-not/
我已成功将 Excel Application 对象添加到 ScriptControl,并在 Excel Application 对象上执行了代码:
这没问题:
Function TestProc()
Dim oScriptCtl As New MSScriptControl.ScriptControl
With oScriptCtl
' init
.Language = "VBScript"
.AllowUI = True
' add Excel application object
.AddObject "app", Application, True
' add procedure
Dim sCode As String
sCode = "Sub TestProc : MsgBox ""hi"" : End Sub"
.AddCode sCode
' run procedure. Msgbox displays.
.Run "TestProc"
End With
' cleanup
Set oScriptCtl = Nothing
End Function
失败:
在这个测试中,m_oScriptCtl 是一个模块范围的变量。当我点击表格时没有任何反应:
Function TestForm()
Set m_oScriptCtl = New MSScriptControl.ScriptControl
With m_oScriptCtl
' init
.Language = "VBScript"
.AllowUI = True
MyForm.Show False
.AddObject "app", Application, True
.AddObject "frm", MyForm, True
.State = Connected
Dim sCode As String
sCode = "Sub frm_Click(): MsgBox Chr(14): End Sub"
.AddCode sCode
End With
End Function
下一个在 .AddCode 上报告以下错误:
Expected ')'
Function TestSheet()
Set m_oScriptCtl = New MSScriptControl.ScriptControl
With m_oScriptCtl
' init
.Language = "VBScript"
.AllowUI = True
.AddObject "app", Application, True
.AddObject "sheet", Sheet2, True
.State = Connected
Dim sCode As String
sCode = "Private Sub sheet_Change(ByVal Target As Range): MsgBox Target: End Sub"
.AddCode sCode
End With
End Function
在接下来的测试中,MyClass定义为:
Public Event MyEvent()
Public Sub TestEvent()
RaiseEvent MyEvent
End Sub
但以下报告 "object does not support property or method" .运行。所以在这种情况下,失败的不是事件——我只是不能 运行 class 中的方法。
Function TestClassEvent()
Set oScriptCtl = New MSScriptControl.ScriptControl
Dim oClass As New MyClass
With oScriptCtl
' init
.Language = "VBScript"
.AllowUI = True
' add objects
.AddObject "app", Application, True
.AddObject "oClass", oClass, True
.State = Connected
' add code
Dim sCode As String
sCode = "Sub oClass_MyEvent() : MsgBox vbNullString : End Sub"
.AddCode sCode
.Run "oClass.TestEvent"
End With
' cleanup
Set oScriptCtl = Nothing
End Function
线索:
有人发帖:
If you totally fail to sink your events, try calling 'ScriptControl1.Modules("Global").CodeObject.Name_Of_Your_Event(ParameterList)' http://computer-programming-forum.com/59-vbscript/4b059f9f6eacfaf0.htm
-- 但我不清楚该解决方法:事件过程不应该是 "called" 明确的,它们应该只是触发。以下几行都给出 "Method or data member not found",在上面的 TestClassEvent
示例中:
m_oScriptCtl.Modules("Global").CodeObject.MyEvent
m_oScriptCtl.Modules("Global").CodeObject.TestEvent
我没有测试以下内容,因为我不太确定如何:
the script control can't handle events from a class in the same project as the application it's being hosted in https://diigo.com/08we68
不确定以下是否相关,不太明白: http://www.programmersheaven.com/discussion/79452/me-activecontrol-and-events
让它起作用的关键是:必须在listener中设置event-firing-object-class 在 之后将两者都添加到脚本控件——而不是之前。意思是,这一行必须在 SC:
内部执行Set oListener.EventFiringObject = oEventFiringObject
这是一个在脚本控件内的对象之间触发和响应事件的工作示例。
在这个例子中:
- 我演示了 2 种事件触发对象:自定义 class 和工作表。
- 自定义 class 在添加到脚本控件 ("sc") 之前实例化。
- 我在自定义 sc 对象中调用了一个方法。
设置演示
- 开始一个新项目(即,在 Excel 中添加一个新的工作簿)。
- 在您的 VB IDE 中,添加对 Microsoft 脚本控件的引用。
- 创建以下 VB 个组件:
代码
Class clsSheetListener
:
Public WithEvents oSht As Worksheet
Private Sub oSht_Change(ByVal Target As Range)
' show changed cell
MsgBox "Sheet Listener" & vbCrLf & "Changed: " & Target.Address _
& vbCrLf & Target.Cells(1).Value2
End Sub
Class clsEventClass
:
Public Event MyEvent(sCaller As String)
Public Sub Raise_MyEvent(sCaller As String)
RaiseEvent MyEvent(sCaller)
End Sub
Class clsClassListener
:
Public WithEvents m_oEventClass As clsEventClass
Private Sub m_oEventClass_MyEvent(sCaller As String)
' show my execution-scope
MsgBox "Class Listener, " & sCaller & " caller"
End Sub
模块 Module1
:
Function Main()
' init scriptcontrol
Set m_oScriptCtl = Nothing
Set m_oScriptCtl = New MSScriptControl.ScriptControl
With m_oScriptCtl
.Language = "VBScript"
.AllowUI = True
' add Excel application object, needed for all Excel methods in script-control
.AddObject "sc_Application", Application, True
' add Sheet2 to the sc
' code executed in sc refers to objects by name, as defined in .AddObject
.AddObject "sc_oSheet", Sheet2, True
' init sheet event-listener, and add to sc
Dim oSheetListener As New clsSheetistener
.AddObject "sc_oSheetListener", oSheetListener, True
' register the sheet-object with its listener in the scriptcontrol
' so the listener can hear the sheet's events
.ExecuteStatement "Set sc_oSheetListener.oSht = sc_oSheet"
' init custom event-firing class object, and add to sc
Dim oEventClass As New clsEventClass
.AddObject "sc_oEventClass", oEventClass, True
' init class-event listener, and add to sc
Dim oClassListener As New clsClassListener
.AddObject "sc_oClassListener", oClassListener, True
' register event-firing object with its listener inside the Script Control
' so the listener can hear the object's events
.ExecuteStatement "Set sc_oClassListener.m_oEventClass = sc_oEventClass"
' cause event to be raised.
' Call from local context, then sc-context.
' it's the same object instance in both cases
oEventClass.Raise_MyEvent "Local"
.ExecuteStatement "sc_oEventClass.Raise_MyEvent ""SC"""
End With
End Function
测试
逐步完成 Main()
。您会看到 Raise_MyEvent
在 clsEventClass
中触发 MyEvent
时,clsClassListener
使用消息框响应事件。
现在切换到Excel前端,在Sheet2的单元格中输入一个值。您会看到 clsSheetListener
使用消息框响应 Change
事件。