Getting ScriptControl to work with Excel 2010 x64
Asked Answered
B

3

12

I am trying to use the solution given to this, however, whenever I try to run the most basic anything, I get an Object not Defined error. I thought this would be my fault (not having installed ScriptControl). However, I tried installing as described in here, to no avail.

I am running Windows 7 Professional x64 with Office 2010 64 bit.

Blackboard answered 15/3, 2012 at 18:29 Comment(2)
To be useful we'd need to see the exact code you tried, and error was got (and from which line of your code)Addle
Tim - I'm having the same problem. I'm using the exact code from Codo's accepted answer to the linked question (linked from the top line of this question). When running the TestJSONAccess Sub, I'm getting an error saying "run-time Error '429': ActiveX component can't create object" from the first line of the InitScriptEngine sub (Set ScriptEnging = New ScriptControl). I have set the reference to the msscript.ocx file.Depone
E
32

You can create ActiveX objects like ScriptControl, which is available on 32-bit Office versions via mshta x86 host on 64-bit VBA version, here is the example (put the code in a standard VBA project module):

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

It has few shortcomings: the separate mshta.exe process running is necessary, which is listed in task manager, and pressing Alt+Tab hidden HTA window is shown:

enter image description here

Also you have to close that HTA window at the end of your code by CreateObjectx86 Empty.

UPDATE

You can make the host window to be closed automatically: by creating class instance or mshta active tracing.

First method assumes you create a class instance as a wrapper, which uses Private Sub Class_Terminate() to close the window.

Note: if Excel crashes while code execution then there is no class termination, so the window will stay in background.

Put the below code in a class module named 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

Put the below code in a standard module:

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

Second method for those who don't want to use classes for some reason. The point is that mshta window checks the state of VBA's Static oWnd variable calling CreateObjectx86 without argument via internal setInterval() function each 500 msec, and quits if the reference lost (either user have pressed Reset in VBA Project window, or the workbook has been closed (error 1004)).

Note: VBA breakpoints (error 57097), worksheet cells edited by user, opened dialog modal windows like Open / Save / Options (error -2147418111) will suspend the tracing since they make application unresponsive for external calls from mshta. Such actions exceptions are handled, and after completion the code will continue to work, no crashes.

Put the below code in a standard module:

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

UPDATE 2

Refused Scriptlet.TypeLib due to noticed permission issues.

Endomorphism answered 30/6, 2016 at 22:49 Comment(12)
amazing solution, it should be the accepted answer, do you think there is a way to automatically close the window at the end of the macro?Henrik
@Henrik I posted the solution for window autoclosing.Endomorphism
@Endomorphism thank you, I'll try that as soon as I'll be back at work on that project, but from the look of it, it should work like a charmHenrik
This was working like a charm (revised standard module approach) for a whole day, and this morning. Then, for no apparent reason, it started erroring here: oWnd.execScript "var Lost, App;": Set oWnd.App = Application at this bit Set oWnd.App = Application. I moved the offending code to be after the setInterval... and it seems to work again. Any thoughts, is that line even needed? Otherwise very cool :)Exacerbate
Actually after moving the line it worked several times then crashed again: CreateObjectx86 Err: 438 - Object doesn't support this property or method on this line: Set oWnd.app = Application , after commenting out the line everything seems to work...Exacerbate
This should be the accepted answer , works like charmAxiom
@Exacerbate The issue is caused by the incorrect property name. oWnd.App is OK, oWnd.app won't work.Endomorphism
@Endomorphism I just face-palmed. Thank you.Exacerbate
Somehow, it seems to loop for a very long time in the For Each oShellWnd In CreateObject("Shell.Application"). Windows loop. I am not sure I understand the code fully but is it required to create a shell for each application? Should this perhaps be limited to the current application? Or perhaps this is a different issue. I am trying to use this to get this working properly: #1745915. I am inserting this as part of MS-Word VBA codeMalarkey
As suggested by @omegastripes, I posted a new question here: #63745366Malarkey
@Endomorphism Hi I am trying to use this solution for Access. Here is my question link #69267742 I saw you code but I don't have 64bit system so I can't set this line systemroot%\syswow64\mshta.exe to create a window. I am using 32bit system. So how can I achieve this? ThanksShanley
If it does not show up it just means it is not correctly installed ! Usually it miss the registry vaues to be known as COM object ! How to do it even by hand is shown on its github page !Jennettejenni
J
5

For the 32 bit version of the control is a 64bit drop in replacement availeable. Google for Tabalacus script control. https://github.com/tablacus/TablacusScriptControl. Control can be compiled with the free VS Versions if you need.

Jennettejenni answered 6/8, 2018 at 6:35 Comment(5)
This worked like a charm, and should be the accepted answer!Unceasing
:) Yes iknow its that easy with it :)Jennettejenni
TablacusScriptControl does NOT work in 64-bit Office newer than 2013. It does not even appear in the Tools->Reference dialog. This was reported to them in July of 2018 and their response was VERY disheartening and sad: Unfortunately, I don't have Excel 2016 and I'm not very familiar with Excel.Domineca
Worked also for me (64bit Office 2016)Derbent
Thanks! This worked for me on office 365. I just downloaded the binary from tablacus.github.io/scriptcontrol_en.html as mentioned in the readme. Ran setup.exe and hit install. Restarted Excel and it just worked.Proletariat
E
3

Sadly, scriptcontrol is a 32bit component only and will not run inside a 64bit process.

Erdei answered 28/6, 2013 at 21:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.