Как реализовать событие в 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
событие с окном сообщения.