【问题标题】:How to Implement An Event in Microsoft Script Control?如何在 Microsoft Script Control 中实现事件?
【发布时间】:2016-09-17 00:50:13
【问题描述】:

我在 MSScriptControl 上阅读的所有文档都说它可以响应添加到其中的对象的事件。

脚本控件允许您编写脚本,该脚本将自动 当对象上的事件发生时触发。 https://msdn.microsoft.com/en-us/library/ms974586.aspx

ScriptControl 将能够接收对象生成的事件 使用 AddObject 方法添加。 http://flylib.com/books/en/1.492.1.154/1/

但我这样做没有成功。我假设这意味着 ScriptControl 内的代码将在添加的对象引发它的事件时触发。我无法让任何人工作。

寻找将 any 对象添加到 ScriptControl 并处理由该控件触发的事件的示例代码。不要关心对象是自定义类、窗体、控件还是内置 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上报告以下错误:

预期的')'

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

但以下报告在 .Run 上“对象不支持属性或方法”。所以在这种情况下,失败的不是事件——我只是无法在类中运行方法。

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

线索:

有人发帖:

如果您完全无法接收事件,请尝试调用 'ScriptControl1.Modules("Global").CodeObject.Name_Of_Your_Event(ParameterList)' http://computer-programming-forum.com/59-vbscript/4b059f9f6eacfaf0.htm

-- 但我不清楚这种解决方法:事件过程不应该被明确地“调用”,它们应该只是触发。在上面的TestClassEvent 示例中,以下几行都给出了“找不到方法或数据成员”:

m_oScriptCtl.Modules("Global").CodeObject.MyEvent
m_oScriptCtl.Modules("Global").CodeObject.TestEvent

我没有测试以下内容,因为我不太确定如何:

脚本控件无法处理同一类中的事件 项目作为它托管的应用程序 https://diigo.com/08we68

不确定以下是否相关,不太明白: http://www.programmersheaven.com/discussion/79452/me-activecontrol-and-events

【问题讨论】:

  • 可能,添加对象只是添加对象而没有该对象的任何代码。就像您将 oClass 添加为对象但未添加其代码一样。我认为这是因为我们设置了 objModule = .Modules.Add("NewModule"),然后我们使用 objModule.AddCode 向它添加代码。所以建议添加一个类,然后将代码添加为“Private WithEvents frm As New UserForm”、“Private Sub frm_Click()”& _ vbNewLine & vbTab &“MsgBox”“Hello, world from added module.”“” & _ vbNewLine & "结束子"
  • 嗨@MukulVarshney,谢谢你的建议。但是,在将对象添加到 ScriptControl 之后,我不知道如何向对象添加代码。您说要添加一个模块,但是我如何将添加的模块与添加的对象关联?你能显示代码吗? -thx

标签: excel vba vbscript scriptcontrol msscriptcontrol


【解决方案1】:

使其工作的关键是:您必须在侦听器类中设置事件触发对象将两者添加到脚本控制——不是以前。意思是,这一行必须在 SC 内部执行:

Set oListener.EventFiringObject = oEventFiringObject

这是一个触发和响应脚本控件内对象之间事件的工作示例。

在这个例子中:

  • 我演示了 2 种事件触发对象:自定义类和工作表。
  • 自定义类在添加到脚本控件(“sc”)之前被实例化。
  • 我在自定义 sc 对象中调用了一个方法。

设置演示

  • 开始一个新项目(即,在 Excel 中添加一个新工作簿)。
  • 在您的 VB IDE 中,添加对 Microsoft Script Control 的引用。
  • 创建以下 VB 组件:

代码

班级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

班级clsEventClass:

Public Event MyEvent(sCaller As String)

Public Sub Raise_MyEvent(sCaller As String)
  RaiseEvent MyEvent(sCaller)
End Sub

班级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_MyEventclsEventClass 中触发MyEvent 时,clsClassListener 使用消息框响应事件。

现在切换到 Excel 前端,并在 Sheet2 的单元格中输入一个值。您将看到 clsSheetListener 使用消息框响应 Change 事件。

【讨论】:

  • 下一个目标是在脚本控制中实例化监听器和/或事件源...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 2011-11-20
  • 1970-01-01
相关资源
最近更新 更多