Excel VBA Compile Error - excel

We have an excel spread sheet which we use and it works for most machines but bombs out with 'Compile Error in Hidden Module - General' on others, and the reason appears to be due to missing References.
We check that Macros is enabled but still doesn't help.
Since we protect this excel spread sheet with a password, we don't want to be giving this password out to our users to check the References, and wondered if anyone had any idea how I can add VBA code to check whether the References required for the excel spread sheet is there and if not then bring up a message box to advise the user.
The References we use are as follows:
Visual Basic For Applications
Microsoft Excel 11.0 Object Library
Microsoft Forms 2.0 Object Library
Microsoft Windows Common Controls 5.0 (SP2)
Alternatively, if anyone has any other suggestions on how to go about this problem, that would be great.

The only reference you have listed that could possibly be missing is the common controls. The rest are default in every version of Excel. The Forms one is only if you have a userform or explicitly set it, but that's not your problem. Common Controls is your problem. It doesn't ship with Office anymore. If you have Visual Studio or VB6 you probably have it. Or an old version of Office like XP Developer Edition.
Anyway, you can check for the existence of the OCX file in the System folder. I don't think it's required to be in that folder, but I've never seen it anywhere else.
It's been quite a while since I've seen a reference to 5.0, so I included how to find 6.0 in the code below. Check to make sure you know what version you're using.
In a standard module:
Private Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Public Function HasCommonControl() As Boolean
Dim sFolder As String
Dim lReturn As Long
Const lSIZE As Long = 255
Const sDLLNAME As String = "COMCTL32.OCX" 'For windows common control 5.0
'Const sDLLNAME As String = "MSCOMCTL.OCX" 'For windows common control 6.0
sFolder = Space(lSIZE)
lReturn = GetSystemDirectory(sFolder, lSIZE)
sFolder = Left$(sFolder, lReturn)
HasCommonControl = Len(Dir(sFolder & Application.PathSeparator & sDLLNAME)) > 0
End Function
Having said all that, why are you using common controls? If it's for a treeview on a userform, then check out this all-vba treeview
http://www.jkp-ads.com/articles/treeview.asp
Since jkp wrote that, I haven't used common controls. So few normal-people PCs have it installed that it's just a pain.

Depending on a reference to a specific Excel or other component version is one possible problem. Switching to late binding would solve that problem, so long as you're careful not to use any commands/objects/methods/properties that are supported in one version and not another.
Following up on RowanC's link (good choice), you can add a reference to Excel, for example and write your code like so:
Dim xlWks as Excel.Worksheet
'Dim xlWks as Object
Once everything's debugged, remove the Excel reference and change the declarations to:
'Dim xlWks as Excel.Worksheet
Dim xlWks as Object
That gives you the benefit of intellisense while coding/debugging but removes the dependency on a specific version of Excel later.
Might be mistaken, but IIRC the Common Controls component is part of Visual Basic, not Office, so unless you distribute it and register it along with your app, it might not be present on some systems.

To try late binding, which doesn't need the references setup (although it may have a performance hit, and it will mean that autocomplete doesn't work in your code) instead of calling excel in the following way:
Dim oExcel As Excel.Application
Set oExcel = CreateObject("Excel.Application")
try calling it this way, and drop the reference to the excel object model.
Dim oExcel As Object
Set oExcel = CreateObject("Excel.Application")

Related

Trying to get clipboard data

I'm trying to get clipboard data through this lines:
Sub GetClipboard()
Dim objData As New MSForms.DataObject
Dim strText
objData.GetFromClipboard
strText = objData.GetText()
MsgBox strText
End Sub
I get the error:
"User-Defined type not defined"
While "Microsoft Office 16.0 Object Library" is selected in Tools> Reference!
Appreciate any help on this.
It looks like you are missing the correct reference.
In this case for the MSForms namespace you need the Microsoft Forms Object Library (e.g. Microsoft Forms 2.0 Object Library reference).
On my installation of Office 2016 I do not have this library that I could reference. But as stated here (https://wellsr.com/vba/2015/tutorials/vba-copy-to-clipboard-paste-clear/) there are problems since Windows 8/10 anyway. The solution is to use the Windows API directly. Which should work on Windows 7 and newer.
In the first link there is an example only for setting data to the clipboard. You asked for retrieving data so a quick internet search revealed this example code which is described as working on Windows x86 and x86_64 and supports setting and getting data from the clipboard (https://francescofoti.com/2013/12/share-the-clipboard-with-vba-and-the-windows-api/).
I have tested the code from the second link to retrieve a string from the clipboard and it worked. I had to fix a minor thing. The Application object on my Office installation does not have a member called hWndAccessApp. One has to replace it with the default hwnd member:
Application.hWndAccessApp
replaced with:
Application.hwnd
You need below
set objData = New MSForms.DataObject

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

How do I load and excel addins in vb.net?

I have to create an excel file in VB.NET to make some calculations trough a excel add-in (if you are asking, no, recreating the add-in inside the program itself is not an option), I have done some research and according to the microsoft.docs website I would have to use my application variable (aka appXl) and write appXl.AddIns.Add([filename]), but it fails every time, again according to the microsoft.docs I should open the workbook.
I tried using appXl.AddIns2.Add([filename]), but it failed too, I tried various solutions found on the internet, but none seem to work, I also tried using the title, or the directory, but it doesn't work
code:
vb.net
Imports Microsoft.Office.Interop
Private appXl As Excel.Application
Private wbXl As Excel.Workbook
Private shXl As Excel.Worksheet
Private AddinXl As Excel.AddIn
Private dataDirectory As String = (String.Format("{0}\Data\", Environment.CurrentDirectory))
Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
dataDirectory &= "AnimalFeed.xlsx"
appXl = New Excel.Application
wbXl = appXl.Workbooks.Open(dataDirectory)
shXl = wbXl.Worksheets("solver")
AddinXl = appXl.AddIns.Add("wba.xlam")
End Sub
it should load the plugin and then be able to use all of its functions inside vb.net, but the debug stops to the AddinXl = appXl.AddIns.Add("wba.xlam") line and it just says "Add method of AddIns class failed".
Have you added Excel in your references?
I'm sorry I can't guide you through this as I haven't used VB.net in ages, but in order to use the Excel objects, you'll need the reference.
You'll know if you have added it when type Excel, the list of possible options will appear.
If not, look for Tools -> References and find Excel probably under Microsoft first. Google vb.net with your version numbers (.Net and Excel) to get an exact guide.

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

Resources