Hacer que ScriptControl funcione con Excel 2010 x64

Resuelto Proto asked hace 12 años • 3 respuestas

Estoy intentando utilizar la solución dada para esto , sin embargo, cada vez que intento ejecutar algo más básico, aparece un Object not Definederror. Pensé que esto sería culpa mía (no haber instalado ScriptControl). Sin embargo, intenté instalar como se describe aquí , sin éxito.

Estoy ejecutando Windows 7 Professional x64 con Office 2010 de 64 bits.

Proto avatar Mar 16 '12 01:03 Proto
Aceptado

Puede crear objetos ActiveX como ScriptControl, que están disponibles en versiones de Office de 32 bits a través del host mshta x86 en la versión VBA de 64 bits. Aquí está el ejemplo (ponga el código en un módulo de proyecto VBA estándar):

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
    Do Until Len(sSignature) = 32
        sSignature = sSignature & Hex(Int(Rnd * 16))
    Loop
    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

Tiene algunas desventajas: mshta.exees necesario ejecutar el proceso por separado, que aparece en el administrador de tareas, y al presionar Alt+ Tabse muestra la ventana HTA oculta:

ingrese la descripción de la imagen aquí

También debes cerrar la ventana HTA al final de tu código mediante CreateObjectx86 Empty.

ACTUALIZAR

Puede hacer que la ventana del host se cierre automáticamente: creando una instancia de clase o un seguimiento activo de mshta.

El primer método supone que crea una instancia de clase como contenedor, que se utiliza Private Sub Class_Terminate()para cerrar la ventana.

Nota: si Excel falla durante la ejecución del código, entonces no hay terminación de clase, por lo que la ventana permanecerá en segundo plano.

Coloque el siguiente código en un módulo de clase llamado 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
        Do Until Len(sSignature) = 32
            sSignature = sSignature & Hex(Int(Rnd * 16))
        Loop
        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

Coloque el siguiente código en un módulo estándar:

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

Segundo método para aquellos que no quieren utilizar clases por algún motivo. El punto es que la ventana mshta verifica el estado de Static oWndla llamada variable de VBA CreateObjectx86sin argumentos a través de setInterval()una función interna cada 500 ms y se cierra si se pierde la referencia (o el usuario presionó Restablecer en la ventana del proyecto VBA o el libro se cerró (error 1004)) .

Nota: Los puntos de interrupción de VBA (error 57097), las celdas de la hoja de trabajo editadas por el usuario, las ventanas modales de diálogo abiertas como Abrir/Guardar/Opciones (error -2147418111) suspenderán el seguimiento ya que hacen que la aplicación no responda a las llamadas externas de mshta. Estas excepciones de acciones se manejan y, una vez finalizadas, el código seguirá funcionando sin fallos.

Coloque el siguiente código en un módulo estándar:

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
    Do Until Len(sSignature) = 32
        sSignature = sSignature & Hex(Int(Rnd * 16))
    Loop
    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

ACTUALIZACIÓN 2

Rechazado Scriptlet.TypeLibdebido a problemas de permisos observados.

omegastripes avatar Jun 30 '2016 22:06 omegastripes

Para la versión de 32 bits del control hay disponible un reemplazo directo de 64 bits. Google para el control de scripts de Tabalacus. https://github.com/tablacus/TablacusScriptControl . El control se puede compilar con las versiones VS gratuitas si es necesario.

Thomas Ludewig avatar Aug 06 '2018 06:08 Thomas Ludewig

Lamentablemente, scriptcontrol es sólo un componente de 32 bits y no se ejecutará dentro de un proceso de 64 bits.

Wolfgang Kuehn avatar Jun 28 '2013 21:06 Wolfgang Kuehn