Vba Excel Trust access to the VBA project model - excel

I need to execute the following lines of code for my client, the problem is that in order to access them I must have activated a certain option within the project, is there any way to avoid that?
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Windows\System32\mshtml.tlb"
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Windows\System32\msxml6.dll"
They are a couple of libraries necessary for the execution of my Macro.
The macro that I am running is as follows:
Sub GetCurrentDate()
Dim S$
With CreateObject("MSXML2.XMLHTTP")
.Open "GET", "http://www.fechadehoy.com/venezuela", False
.send
S = .responseText
End With
With CreateObject("htmlfile")
.body.innerHTML = S
MsgBox .getElementById("fecha").innerText
End With
End Sub
libraries needed for the execution of my macro
Microsoft XML, v6.0
Microsoft HTML Object Library

in order to access them I must have activated a certain option within the project, is there any way to avoid that?
The option isn't within the project, it's at the host application level (Excel): whether programmatic access to the VBIDE API is trusted or not is an important part of macro security settings, and no, there isn't any way around it.
Any programmatic way to circumvent this security setting would make a huge gaping security hole every macro-virus in the world would jump into.
But you don't need to do this. Your code is creating instances of classes located in these libraries using CreateObject, not the New operator: the references are not needed.
With CreateObject("MSXML2.XMLHTTP") ' returns an Object/XMLHTTP reference
.Open ... 'late-bound member call (no intellisense, no compile-time validation)
'...
End With
CreateObject uses the specified ProgID string to find the registration in the Windows Registry, locate the type library, create an instance of the type, and return a reference to that object - everything is resolved at run-time (hence "late" bound), and as long as the ProgID exists in the registry and there's no typo in the late-bound code (Option Explicit can't save you from those), everything "just works".
If you used the New keyword instead...
With New MSXML2.XMLHTTP ' returns an XMLHTTP reference
.Open ... 'early-bound member call (with intelilsense and compile-time validation)
'...
End With
This couldn't be compiled without a project reference to the MSXML2 library.

Related

the remote server machine is unavailable error '462'

I have an excel userform a screen shot of which I would like to include in an outlook email. It works fine on my main programming computer, but when I run the same program on other computers I get the above error. The excel workbook is in the cloud and is run from the cloud (google drive) on various computers. the code is:
Function outlookEmail()
Dim doc As Object, rng As Range
Application.SendKeys "(%{1068})"
DoEvents
'ActiveSheet.Paste
With CreateObject("Outlook.Application").CreateItem(0)
.display
Set doc = .GetInspector.WordEditor
doc.Range(0, 0).Paste
.To = sDetail.Cells(myRow, headerDict.item("email"))
.Subject = "documents for you"
End With
End Function
the error is on the set doc line, if I mark it out, the error moves the the next line: doc.range...
Outlook is a singleton. That means you can't run two instances of the application at the same time. If the Outlook Application is already running under the different security context you may get into troubles. So, I'd suggest checking whether Outlook is already running and make sure it is running under the same security context, so you could reach the instance.
You can use the Visual Basic GetObject function to return a reference to the Application object that represents a session that is already running. Note that because there can be only one instance of Outlook running at any given time, GetObject usually serves little purpose when used with Outlook. CreateObject can always be used to access the current instance of Outlook or to create a new instance if one does not exist. However, you can use error trapping with the GetObject method to determine whether Outlook is currently running.
Read more about that in the Automating Outlook from Other Office Applications article.

Workbook Subroutines cannot be called directly by name anymore from VB6

I have a vb6 program that calls Macros from an Excel file.
Until recently it worked fine (for years), but now it throws an error.
We get a runtime 438 "Object doesn't support this property or method" error.
As an example you can use this simple vb6 program:
Set App = CreateObject("Excel.Application")
Set wrkbook = App.Workbooks.Open(fileName)
App.visible = True
wrkbook.Test
The above code doesn't work anymore.
Instead, if we replace the last line with this:
wrkbook.Application.Run "ThisWorkbook.Test"
it works.
The Excel reference used for this, was "Microsoft Excel 16.0 Object Library"
This has been tested against Excel 2010, 2013, Excel365 with the same results.
Also security settings are all set off in Excel.
Before changing my entire codebase and use Application.Run, I would know why this is happening.
Also using Application.Run has also some downsides, like calling both private & public subs and exceptions thrown are not propagated back to vb6.
Are there other considerations for using Application.Run?
Did Microsoft changed something lately (Scurity update), or am I doing something wrong?
I found the problem, thanks to #UuDdLrLrSs comment.
Problem was the use of early binding.
All Excel objects should use late binding.
More specific, the workbook should be declared as object:
Dim wrkbook As Object 'New Excel.Workbook
Otherwise it cannot recognize/find your Macro method.

VBA cannot create new CXMLHTTPHandler

I'm currently working on late binding due to some issues with macros not working in Excel 2013 when they worked fine in 2010. Obviously, 2010 utilizes 14.0 object library whereas 2013 uses 15.0.
Dim myHttpRequest As Object
Dim myHttpHandler as Object
Set myHttpRequest = CreateObject("MSXML2.XMLHTTP")
Set myHttpHandler = CreateObject("CXMLHTTPHandler")
This yields an ActiveX cannot create object error. I've spent over a day looking into this.
Is there some sort of resource that has to be added in order for these objects to work? Do these objects even exist in Excel's 15.0 Object Library?
I'm completely at a loss of what to do as this usually works.
I strongly suspect, looking at this post http://dailydoseofexcel.com/archives/2006/10/09/async-xmlhttp-calls/
that you are dealing with a user defined class. If that is the case you need to copy across that class, follow the steps outlined in the link, and then simply create a new instance of that class, without need for late binding as no library is involved.
An additional step is to convert code in that class to late bound as required if other libraries are early bound referenced.
As per that link:
Dim MyXmlHttpHandler As CXMLHTTPHandler
' Create an instance of the wrapper class.
Set MyXmlHttpHandler = New CXMLHTTPHandler
The additional steps quoting from that link are:
Export and remove the CXMLHTTPHandler class to a known directory
Open that file with notepad
Find the OnReadyStateChange sub, and add this text after the signature:Attribute OnReadyStateChange.VB_UserMemId = 0
Save, close and reimport the class module into the project

VBA Dim Object error

If I Run
Sub test()
Dim Template_Excel_Instance As excel.application
Set Template_Excel_Instance = CreateObject("excel.application")
End Sub
my code breaks with an error "Automation Error, Library not registered"
If I run
Sub test()
Dim Template_Excel_Instance As object
Set Template_Excel_Instance = CreateObject("excel.application")
End Sub
It runs fine. Is there any way to fix this? Reason I ask is that this issue only affects one PC, despite having the same references as all other PCs. The first error is not coming up anywhere else
Does that PC have a different version of Excel?
The problem is with As Excel.Application. If you don't have the appropriate reference defined, then the VBA compiler will not recognise the type. Yes, VBA does have a compilation step. If you do have the reference defined, then this is sensitive to the application version (just the major part of the application version I think), so is therefore inherently non-portable.
In your latter example, you are using late binding, so only COM object registration is required, not any specific library to be added to your project. For portability, this is the way to go.
Firstly, have you tried repairing the install?
Secondly, is there a reason you are instantiating a second instance of Excel?
Thirdly, let's get a grip on what is happening, please run this code and report back.
Option Explicit
Sub TestWhatVersionDoesCreateObjectReturn()
Dim obj As Object
Set obj = CreateObject("Excel.Application")
Debug.Print obj.Version
End Sub
Sub TestWhatOtherVersionsAreCreatable()
Dim lLoop As Long
For lLoop = 7 To 16
Dim obj As Object
Set obj = Nothing
On Error Resume Next '///set break on unhadnled errors
Set obj = CreateObject("Excel.Application." & CStr(lLoop))
On Error GoTo 0
If Not obj Is Nothing Then Debug.Print obj.Version
Next
End Sub
Also, look for multiple installations of Excel. The code at this blog page will read your registry and write the results to an Excel worksheet. You say you have repaired the install but there might be other Excel installations interfering. The code in that blog will highlight multiple Excel installs.
Ok, from your feedback you say all the Excel libraries version return 14, implying no multi version installs. Hmmm, we ought to consider that actually the library that error is complaining about isn't Excel but a dependency.
Other possible leads
Social MSDN - automation error. Library not registered - solved by cleaning registry of legacy "Microsoft.Office.Interop.Excel" keys

How to auto check the 'Microsoft ActiveX Data Objects x.x Library' from the Tools --> References?

We share our Excel Macro - MS Access project with our client.
They don't know to select the 'Microsoft ActiveX Data Objects x.x Library' from the Tools --> References.
Any code to automatically update MS ADO library settings?
Note: In Office we are using MS 2010. I think the client's office is using Micorsoft XP.
I suggest above to use late binding, but you could do something like this (my code exactly as used in PPT 2010, should be easy enough to adapt to Access but I do not ever use access).
You may need to change the ADODBReference constant for use in XP. Or you could add another constant and a logic check to see what Application.Version and load from the appropriate destination path.
Public Const ADODBReference As String = "C:\Program Files (x86)\Common Files\System\ado\msado15.dll"
Sub PPT_AddRefToADODBLibrary()
'Adds a programmatic reference to ADODB library if one doesn't already exist
'ADODBReference is a public const refers to Microsoft ActiveX Data Objects 6.0 Library
If Not PPT_RefExists(ADODBReference, "Microsoft ActiveX Data Objects 6.0 Library") Then
Application.VBE.ActiveVBProject.References.AddFromFile _
ADODBReference
Else:
'Already installed
End If
End Sub
The sub above calls on this custom function, which first iterates the active References
Function PPT_RefExists(refPath As String, refDescrip As String) As Boolean
'Returns true/false if a specified reference exists, based on LIKE comparison
' to reference.description.
Dim ref As Variant
Dim bExists As Boolean
'Assume the reference doesn't exist
bExists = False
For Each ref In Application.VBE.ActiveVBProject.References
If ref.Description Like refDescrip Then
PPT_RefExists = True
Exit Function
End If
Next
PPT_RefExists = bExists
End Function
Trying to simply turn it on with a code like this:
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Program Files (x86)\Common Files\System\ado\msado15.dll"
you may come across three problems: it is already installed, earlier version is installed, the file path is invalid. So my logic is as follows:
Code loops through all refs and checks if ref to Microsoft ActiveX Data Objects 6.0 Library is installed.
If not installed, then it tries to install it with error handling.
If failure will occur, it means that either earlier version i.e. Microsoft ActiveX Data Objects 2.8 is installed (could be checked while looping) or the file path is invalid.
Code:
Sub AddReferenceMicrosoftActiveXDataObjectsLibrary()
Const MyRefPath As String = "C:\Program Files (x86)\Common Files\System\ado\msado15.dll"
Dim ref As Variant
Dim IsInstalled As Boolean: IsInstalled = False
For Each ref In Application.VBE.ActiveVBProject.References
Debug.Print ref.FullPath
If ref.FullPath = MyRefPath Then IsInstalled = True
Next
If IsInstalled = False Then
On Error GoTo err:
Application.VBE.ActiveVBProject.References.AddFromFile MyRefPath
On Error GoTo 0
Debug.Print "Just installed"
Exit Sub
Else
Debug.Print "Already installed"
End If
Exit Sub
err:
MsgBox "Probably earlier version of Microsoft ActiveX Data Objects is already installed or other error occurred"
End Sub
I think late binding is the only way.
I made an Excel-based application for my office, and every time i prepare new version there is about 10% of users I have to visit to add references.
I found out, that since these computers have different Windows versions, for some dll's there is no version which would exist on each computer.
This makes adding references from code more difficult and I do not want to use late binding.
Thats a pity - most of the dll's functionality I use is compatible among all versions.

Resources