使ScriptControl与Excel 2010 x64一起使用

时间:2012-03-15 18:29:09

标签: vba excel-vba com excel-2010 scriptcontrol

我正在尝试使用this给出的解决方案,但是,每当我尝试运行最基本的任何内容时,我都会遇到Object not Defined错误。我认为这将是我的错(没有安装ScriptControl)。但是,我尝试按照here中所述进行安装,但无济于事。

我正在使用Office 2010 64位运行Windows 7 Professional x64。

4 个答案:

答案 0 :(得分:17)

您可以创建像ScriptControl这样的ActiveX对象,这些对象在32位Office版本上通过64位VBA版本上的mshta x86主机提供,这是示例(将代码放在标准VBA项目模块中):

Option Explicit

Sub Test()

    Dim oSC As Object

    Set oSC = CreateObjectx86("ScriptControl") ' create ActiveX via x86 mshta host
    Debug.Print TypeName(oSC) ' ScriptControl
    ' do some stuff

    CreateObjectx86 Empty ' close mshta host window at the end

End Sub

Function CreateObjectx86(sProgID)

    Static oWnd As Object
    Dim bRunning As Boolean

    #If Win64 Then
        bRunning = InStr(TypeName(oWnd), "HTMLWindow") > 0
        If IsEmpty(sProgID) Then
            If bRunning Then oWnd.Close
            Exit Function
        End If
        If Not bRunning Then
            Set oWnd = CreateWindow()
            oWnd.execScript "Function CreateObjectx86(sProgID): Set CreateObjectx86 = CreateObject(sProgID): End Function", "VBScript"
        End If
        Set CreateObjectx86 = oWnd.CreateObjectx86(sProgID)
    #Else
        If Not IsEmpty(sProgID) Then Set CreateObjectx86 = CreateObject(sProgID)
    #End If

End Function

Function CreateWindow()

    ' source http://forum.script-coding.com/viewtopic.php?pid=75356#p75356
    Dim sSignature, oShellWnd, oProc

    On Error Resume Next
    sSignature = Left(CreateObject("Scriptlet.TypeLib").GUID, 38)
    CreateObject("WScript.Shell").Run "%systemroot%\syswow64\mshta.exe about:""<head><script>moveTo(-32000,-32000);document.title='x86Host'</script><hta:application showintaskbar=no /><object id='shell' classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object><script>shell.putproperty('" & sSignature & "',document.parentWindow);</script></head>""", 0, False
    Do
        For Each oShellWnd In CreateObject("Shell.Application").Windows
            Set CreateWindow = oShellWnd.GetProperty(sSignature)
            If Err.Number = 0 Then Exit Function
            Err.Clear
        Next
    Loop

End Function

缺点很少:必须运行单独的mshta.exe进程,在任务管理器中列出,按 Alt + Tab 隐藏的HTA窗口是所示:

enter image description here

此外,您必须通过CreateObjectx86 Empty关闭代码末尾的HTA窗口。

<强>更新

您可以自动关闭主机窗口:通过创建类实例或mshta主动跟踪。

第一种方法假设您创建一个类实例作为包装器,它使用Private Sub Class_Terminate()来关闭窗口。

注意:如果Excel在执行代码时崩溃,则没有类终止,因此窗口将保留在后台。

将以下代码放在名为cMSHTAx86Host的类模块中:

    Option Explicit

    Private oWnd As Object

    Private Sub Class_Initialize()

        #If Win64 Then
            Set oWnd = CreateWindow()
            oWnd.execScript "Function CreateObjectx86(sProgID): Set CreateObjectx86 = CreateObject(sProgID) End Function", "VBScript"
        #End If

    End Sub

    Private Function CreateWindow()

        ' source http://forum.script-coding.com/viewtopic.php?pid=75356#p75356
        Dim sSignature, oShellWnd, oProc

        On Error Resume Next
        sSignature = Left(CreateObject("Scriptlet.TypeLib").GUID, 38)
        CreateObject("WScript.Shell").Run "%systemroot%\syswow64\mshta.exe about:""<head><script>moveTo(-32000,-32000);document.title='x86Host'</script><hta:application showintaskbar=no /><object id='shell' classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object><script>shell.putproperty('" & sSignature & "',document.parentWindow);</script></head>""", 0, False
        Do
            For Each oShellWnd In CreateObject("Shell.Application").Windows
                Set CreateWindow = oShellWnd.GetProperty(sSignature)
                If Err.Number = 0 Then Exit Function
                Err.Clear
            Next
        Loop

    End Function

    Function CreateObjectx86(sProgID)

        #If Win64 Then
            If InStr(TypeName(oWnd), "HTMLWindow") = 0 Then Class_Initialize
            Set CreateObjectx86 = oWnd.CreateObjectx86(sProgID)
        #Else
            Set CreateObjectx86 = CreateObject(sProgID)
        #End If

    End Function

    Function Quit()

        #If Win64 Then
            If InStr(TypeName(oWnd), "HTMLWindow") > 0 Then oWnd.Close
        #End If

    End Function

    Private Sub Class_Terminate()

       Quit

    End Sub

将以下代码放在标准模块中:

Option Explicit

Sub Test()

    Dim oHost As New cMSHTAx86Host
    Dim oSC As Object

    Set oSC = oHost.CreateObjectx86("ScriptControl") ' create ActiveX via x86 mshta host
    Debug.Print TypeName(oSC) ' ScriptControl
    ' do some stuff

    ' mshta window is running until oHost instance exists
    ' if necessary you can manually close mshta host window by oHost.Quit

End Sub
对于那些因某些原因不想使用课程的人来说,

第二种方法。关键是mshta窗口每隔500毫秒通过内部Static oWnd函数检查VBA的CreateObjectx86变量调用setInterval()变量的状态,如果参考丢失(用户使用)则退出已在VBA项目窗口中按下重置,或者工作簿已关闭(错误1004))。

注意:VBA断点(错误57097),用户编辑的工作表单元格,打开的对话框模式窗口(如打开/保存/选项(错误-2147418111))将暂停跟踪,因为它们使应用程序无响应来自mshta的外部调用。处理此类操作异常,完成后代码将继续工作,不会崩溃。

将以下代码放在标准模块中:

Option Explicit

Sub Test()

    Dim oSC As Object

    Set oSC = CreateObjectx86("ScriptControl") ' create ActiveX via x86 mshta host
    Debug.Print TypeName(oSC) ' ScriptControl
    ' do some stuff

    ' mshta window is running until Static oWnd reference to window lost
    ' if necessary you can manually close mshta host window by CreateObjectx86 Empty

End Sub

Function CreateObjectx86(Optional sProgID)

    Static oWnd As Object
    Dim bRunning As Boolean

    #If Win64 Then
        bRunning = InStr(TypeName(oWnd), "HTMLWindow") > 0
        Select Case True
            Case IsMissing(sProgID)
                If bRunning Then oWnd.Lost = False
                Exit Function
            Case IsEmpty(sProgID)
                If bRunning Then oWnd.Close
                Exit Function
            Case Not bRunning
                Set oWnd = CreateWindow()
                oWnd.execScript "Function CreateObjectx86(sProgID): Set CreateObjectx86 = CreateObject(sProgID) End Function", "VBScript"
                oWnd.execScript "var Lost, App;": Set oWnd.App = Application
                oWnd.execScript "Sub Check(): On Error Resume Next: Lost = True: App.Run(""CreateObjectx86""): If Lost And (Err.Number = 1004 Or Err.Number = 0) Then close: End If End Sub", "VBScript"
                oWnd.execScript "setInterval('Check();', 500);"
        End Select
        Set CreateObjectx86 = oWnd.CreateObjectx86(sProgID)
    #Else
        Set CreateObjectx86 = CreateObject(sProgID)
    #End If

End Function

Function CreateWindow()

    ' source http://forum.script-coding.com/viewtopic.php?pid=75356#p75356
    Dim sSignature, oShellWnd, oProc

    On Error Resume Next
    sSignature = Left(CreateObject("Scriptlet.TypeLib").GUID, 38)
    CreateObject("WScript.Shell").Run "%systemroot%\syswow64\mshta.exe about:""<head><script>moveTo(-32000,-32000);document.title='x86Host'</script><hta:application showintaskbar=no /><object id='shell' classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object><script>shell.putproperty('" & sSignature & "',document.parentWindow);</script></head>""", 0, False
    Do
        For Each oShellWnd In CreateObject("Shell.Application").Windows
            Set CreateWindow = oShellWnd.GetProperty(sSignature)
            If Err.Number = 0 Then Exit Function
            Err.Clear
        Next
    Loop

End Function

答案 1 :(得分:3)

可悲的是,scriptcontrol只是一个32位组件,不会在64位进程内运行。

答案 2 :(得分:0)

对于32位版本的控件,可用替换版本降低了64位。 Google for Tabalacus脚本控件。 https://github.com/tablacus/TablacusScriptControl。如果需要,可以使用免费的VS版本来编译控件。

答案 3 :(得分:-2)

在VBA编辑器上,转到工具&gt;引用并启用Microsoft脚本控制。