Как реализовать событие в Microsoft Script Control?

Все документы, которые я читал на MSScriptControl, говорят, что он может отвечать на события объектов, добавленных к нему.

элемент управления script позволяет вам писать скрипт, который будет автоматически запускаться при возникновении события на объекте. https://msdn.microsoft.com/en-us/library/ms974586.aspx

ScriptControl сможет принимать события, генерируемые объектами, добавленными с использованием метода AddObject. http://flylib.com/books/en/1.492.1.154/1/

Но я не добился успеха в этом. Я предполагаю, что это означает, что код внутри ScriptControl сработает, когда добавленный объект вызовет событие. Я не могу заставить кого-либо работать.

Поиск примера кода добавления любого объекта в ScriptControl и обработки событий, запускаемых этим элементом управления. Не важно, является ли объект пользовательским классом, формой, элементом управления или встроенным объектом Excel, таким как Worksheet.

Под управлением Office 2010 32bit на Win Server 2008 64bit.

Открыт для альтернативных методов, таких как WSH, но Тушар Мехта не добился успеха с этим здесь http://dailydoseofexcel.com/archives/2009/08/19/using-vbscript-to-monitor-office-eventsor-not/

Я успешно добавил объект приложения Excel в ScriptControl и выполнил код для объекта приложения Excel:

Это работает без проблем:

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

1 ответ

Решение

Ключом к тому, чтобы заставить его работать, является: Вы должны установить объект срабатывания события в классе слушателя после добавления обоих в элемент управления Script, а не до. Это означает, что эта строка должна быть выполнена внутри SC:

Set oListener.EventFiringObject = oEventFiringObject

Вот рабочий пример запуска и реагирования на события между объектами внутри элемента управления Script.

В этом примере:

  • Я демонстрирую 2 вида объектов, запускающих события: пользовательский класс и рабочий лист.
  • Пользовательский класс создается перед добавлением его в scriptcontrol ("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_MyEvent пожары MyEvent в clsEventClass, clsClassListener отвечает на событие сообщением.

Теперь переключитесь на внешний интерфейс Excel и введите значение в ячейку в Sheet2. Вот увидишь clsSheetListener ответить на Change событие с окном сообщения.

Другие вопросы по тегам