Workbook Subroutines cannot be called directly by name anymore from VB6 - excel

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.

Related

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

Difference between Excel.ThisWorkbook and just ThisWorkbook?

I have some VBA code that ran fine in Excel at my desk at work but at home it's crashtastic. Turns out all I had to do was change
Set shtObj = ThisWorkbook.Sheets(1)
to
Set shtObj = Excel.ThisWorkbook.Sheets(1)
Anyone know why? Our organization has just moved to a SharePoint platform, which I suspect is causing all manner of voodoo to creep up, but I'm just guessing.
Does it work if you change it back to ThisWorkbook?
I suspect it will, and the reason would be because the VBA recompiled itself (and didn't compile properly the first time - hence the propensity to crash).
Recompilation occurs when the version details embedded in the file differ from the version of Office/VBA in use, or there's a change from 32 to 64 bit Office. Editing the line is enough to recompile the line, so adding Excel. before ThisWorkbook was enough to make it recompile. Removing Excel. before ThisWorkbook should force it to recompile again.
The only other thing it might be is if there's a variable named ThisWorkbook, but then I'd expect you to get error 91, "Object variable or With block variable not set", or some other error, but not a crash.
ThisWorkbook is a global-scope Workbook object that you can use to refer to the workbook instance that contains the very VBA code that you're looking at.
So in theory, an unqualified ThisWorkbook is exactly the same object as Excel.ThisWorkbook or Application.ThisWorkbook.
Proof:
Sub Test()
Debug.Print ObjPtr(ThisWorkbook), _
ObjPtr(Excel.ThisWorkbook), _
ObjPtr(Application.ThisWorkbook)
End Sub
Outputs 3 times the same pointer address.
Excel.ThisWorkbook is a member (Property Get) of the hidden Excel._Global module, and Application.ThisWorkbook is a member (Property Get) of the Excel.Application class.
Not sure what's up with your file, but there's not supposed to be any difference between the two.
This appears to be a bug in my particular user/profile. Others are now using the code/workbook with no reports of trouble. Yay!!?

Compatibility Between MS-Access 2003 and MS-Excel 2013

This is similar to a question that I've asked yesterday, but I've managed to find a fair bit more information: enough to warrant a new question, I feel.
My office has recently moved to Windows 7 along with Office 2013 - with the except of Access which has stayed as 2003.
Access works absolutely fine except when I try to automate Excel. This is a feature of nearly all my applications.
When I load an old project, the reference is automatically updated to "Microsoft Excel 15.0 Object Library" - it is held as an EXE file in Program Files (x86). Note: it does not say the reference is missing.
When I try to run any code which uses early binding, it fails with the following error message: "Error in loading DLL"
I've since tried late binding by doing the following:
Dim app As Object
Dim wb As Object
Set app = CreateObject("Excel.Application")
app.Visible = True
Set wb = app.Workbooks.Add
This creates the Application, it becomes visible, a Workbook is added, but then I get the following error: "Run-time error '1004':
Application-definted or object-defined error"
If I try to access VBA in the new Workbook I get the following error: "An error occurred initializing the VBA libraries (1004)" The Workbook is loaded in "Compatibility Mode"
The above leads me to believe that the 2 applications may not be compatable, but the following is worth considering:
If I try to use early binding I don't get the Intellisense drop-downs but words like Workbook and Worksheet do auto-capitalise themselves as you would normally expect them to. The code won't compile at all if I don't have the reference set, but it does compile - and throw and error - when it is. I've since tried Word 2013 - who's Object Reference is an OLB file rather than EXE - and I get the full Intellisense features I would except, but it still throws the same error when trying to run.
In a nut shell, does anyone know if I stand any chance of having the 2 work together?
Thanks

Excel VBA Compile Error

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")

Resources