I have an interface IReadable where I declare:
Public Function getFields() As Dictionary
End Function
Public Function getData()
End Function
The interface's instancing property is set to publicNotCreatable
I have an Excel sheet that implements this interface and these methods (details not important).
From module mApp, I apply the following code from a sub routine:
Dim oSheet As IReadable
Set oSheet = ThisWorkbook.Sheets("tbl_deals") 'Compile error
When the VBA gets compiled via the menu Debug - Compile VBAProject, everything runs fine. Strangely, the code only gets run once.
If I try to run the code a second time, I get a Type Mismatch error.
In order to make the code run again, I need to switch the status of the interface to private and back, recompile, and the code runs again a single time (the second time, the code returns a type mismatch error again).
Any ideas on how to solve this problem, to make the code run stable without needing to recompile every time?
Edit: This is a strange problem. I thought it might have been related to pollution of the compiled code, but when re-creating the case in a new Excel workbook, the identical problem persists.
Use code name of worksheet instead of displayed name:
Related
I'm having this staggering problem in creating a reference at runtime.
In short: I have an addin referenced in another addins, all created by myself and all working fine (except for some annoying popup which appears on loading Excel). As a workaround to this annoyance, I removed the existing reference to create it later, at runtime. But when I try creating the reference, it returns an "Name conflicts with existing module, project, or object library" error popup, and the reference is not created--which makes no sense, because if I create the reference at design time it works perfectly. There is no module or project with repeated name.
Now explaining a little further.
I have four kinda-complex Excel applications I'd had developed for my job. Each one is a VBA project, distributed as Excel Addins (.xlam).
Additionally, I have a fifth project with functions common to the other four. This fifth project is referenced in the other ones (via Tools -> References). So now, all I have to do is to call them as any API outside referenced function (commonProject.Function (arg1, arg2, arg3 etc)).
Unfortunately, I had some problems with a popup message (here) and the workaround seems to be referencing the fifth project in the other ones at runtime.
In order to do this, I uninstalled three of the other four Addins, remaining only one, and used the following code in its Workbook_Open event:
Private Sub Workbook_Open()
Dim strNamePath As String
Dim bolAddinIsRefered as Boolean
Dim oRef As Variant
strNamePath = "c:\etc\etc\etc\Filename.xlam"
For Each oRef In ThisWorkbook.VBProject.References
If oRef.FullPath = strNamePath Then bolAddinIsRefered = True
Next oRef
If bolAddinIsRefered = False Then ThisWorkbook.VBProject.References.AddFromFile strNamePath
End Sub
The problem is, when I used to create the reference at design time by hand, it worked mostly fine (except for the annoying popup I'm now trying to circumvent). But when I try creating the Reference at runtime, it returns an "Name conflicts with existing module, project, or object library" error popup, and the reference is not created.
I have verified the module and worksheet names and there is no duplicated one.
Does anyone have any idea how to prevent this error?
it seems after one and a half day struggling with a problem, when you ask the question on StackOverflow the solution just pops in your mind.
I'd already tried to change both projects names, even internal functions or subs resembling the same name. But I had not looked upon the FILE NAME!
As my solution is called Sisyphus, the filenames of all addins started with "Sisyphus"--"Sisyphus Common Functions.xlam", "Sisyphus DocMerge.xlam" etc.
The problem was VBA was comparing the first word in filename. I removed spaces and it worked well. Now my filenames are "SisyphusCommonFunctions.xlam", "SisyphusDocMerge.xlam" etc. and the referencing in runtime works all right.
Thank you for your time, I'll let this Question and Answer here, because it can be usefull to someone.
This is a weird error. It only occurs on some machines here, but not all of them. Furthermore, I researched this website and there are no solutions that I can see that cover this.
I receive this error when attempting to run some VBA code in an excel document.
The line of code it occurs in is in the
Private Sub UserForm_Initialize()
event.
The line of code is:
Set objTest = CreateObject("MTRClassLibrary.MTRTestComClass")
As I mentioned previously, the code only errors out on some of the machines here but not all of them.
It is not clear where and how the objTest instance is declared in the code. Also, you need to make sure the corresponding object is registered on the problematic machine. The CreateObject can't locate applications with ProgId passed as a parameter. Try to check the Windows registry for the string passed.
See Object variable not set (Error 91) for all possible cases.
I'm trying to keep alive an old Excel VBA program, and my client has asked me to run some existing code on startup (instead of having to click a button).
So, I'm following this tutorial here.
It kinda works ... ie when the excel files is open the MsgBox prompts appear but with blanks or 0s. However that only happens when I don't include the first line:
Declare Function GetCommandLineA Lib "Kernel32" () As String
when I include that, I get this error message:
Compile Error: Constants, fixed-length strings, arrays, user-defined types and Declare statements not allowed as Public members of object modules.
So - how do I do it?
The Sub Workbook_Activate is Private and I don't think I can change that, can I?
Posting for other confused people:
I was trying to run it from within the ThisWorkbook sub, and what Pᴇʜ rightly pointed out was that you have to create this code in a normal module, and then call that module's sub FROM the ThisWorkbook sub.
thank you Pᴇʜ
I have a VBA Excel model which I have separated into two separate workbooks:
InputsWB, which contains all the inputs for the model, and
RunnerWB, which contains the bulk of the VBA code (and all the class modules live here).
Depending on the needs of the user, the InputsWB can either call the macro in the RunnerWB or the RunnerWB can call multiple versions of the InputsWB. The detail doesn't matter for this question but the two workbooks need to be separated.
Mysteriously, after the split I sometimes get a Run-time 1004 error with the message Cannot Run Visual Basic Editor Because of a Syntax error. If I Debug + F5 then the code runs until it encounters the next Application.Calculate.
I have seen many similar questions while recording macros, or on Application.Calculate. I think mine is related to the Application.Calculate, but those answers don't explain why this happens. Some reasons I can think off, but cannot confirm online is:
There are Modules in the two workbooks with the same names (although I've changed the modules names in the InputsWB but still get the error on occasion.
There are VBA functions in the two workbooks with the same names
Are there any other reasons why I could be getting these errors?
UPDATE (2019/12/02)
I finally realised why I got this error. I am calling a macro in my RunnerWB from my InputsWB. However, there was a duplicate function declared in my RunnerWB. Usually, this would give a Compile error: ambigious name detected when the macro was initiated from ThisWorkbook. However, because it was initiated from another workbook I got the Syntax error explained above.
UPDATE (2020/07/22)
I am now getting this error again on Application.Calculate right at the end of the run. Which breaks me is that I use Application.Calculate many times during the run.
UPDATE (2020/07/23)
I found the issue that caused the bug at last.
I had a sub called Main in a Module called Main
One of the buttons in my workbook referred to this button, and because the names are the same it links it as Main!Main
Later I renamed the module to MainSub. The button still worked, but something inside VBA was broken which was triggered in some Application.Calculate executions.
Conclusion
Never give your sub the same name as your module in VBA, as this may cause problems down the line.
Any help with dynamically loading of classes /variables in VBA?
I have an excel sheet and other few dependent sheets, depending on the requirement, on click of a button I am loading other sheets.
Say Main workbook -> Loads sheet1.xlam and related classes ( cls_one.cls) on click of button.
I am using below code to load sheet1.xlam and cls_one.cls
Step 1: Load Main.xlsm
Step 2 load - sheet1.xlsm
Set addedWs = ActiveWorkbook.Sheets.Add(Type:=path, after:=ActiveWorkbook.Sheets(ActiveWorkbook.Sheets.count))
Step 3: Load Cls_one.cls dynamically using the below method.
Public Function InsertClass(ByRef oWB As Workbook, ByVal className As String, ByVal filePath As String, Optional bUAT As Boolean = False) As Boolean
On Error GoTo Errhandler
oWB.VBProject.VBComponents.Import filePath
InsertClass = True
Exit Function
Errhandler:
If err <> 0 Then
If Not bUAT Then
MsgBox (err.Description)
End If
err.Clear
End If
InsertClass = False
End Function
Above code works fine, however, I have a reference to cls_one in sheet1.xlsm which never works, on loading or give error Undefined object error.
Public Myclassone As cls_one
this variable declaration is in sheet1.xlsm.
I tried flipping steps loading class first and sheet1.xlam next, but still getting the same error with Excel 2013, this piece of code works fine with 2010.
Trying to understand what is the best way to reference dynamically loaded classes in forms or other classes?
Also, I tried changing error preferences in tools -> Options -> Break on Unhandledexception.
You can't early-bind to something that's only going to exist at run-time, by definition - there's no way that could have worked:
Public Myclassone As cls_one
If cls_one doesn't exist at compile-time, then the module can't be compiled.
this piece of code works fine with 2010
No. This piece of code works fine if it's not in any execution path that involves the module declaring a public variable of a type that doesn't exist... regardless of what version the host application is (this behavior is purely VBA, nothing to do with Excel).
That's kind of a hack though: a VBA project will not compile (through Debug -> Compile), but will happily run anyway if the entry point doesn't involve loading the module: that's because of the somewhat-interpreted nature of VBA.
Proof:
Module1
Option Explicit
Public foo As Something '<~ undefined, won't compile
Module2
Option Explicit
Public Sub Test()
Debug.Print "I can run even if the project doesn't compile!"
End Sub
You can run Module2.Test regardless of whether the project compiles, because Module1 isn't in the picture at all. Now change Module2.Test to this:
Public Sub Test()
foo.DoStuff '<~ expect fireworks
End Sub
When I ran this, Excel just outright crashed.
So the bottom line is this: you can reference a non-existing class in a module. The project won't be compilable, but if no code references the non-existing class then the project will be executable anyway, and the non-compilable module can then be executed in another execution context (i.e. from a separate entry point), after the class is added.
I would not recommend using non-compilable code for anything remotely important though, since doing that takes away the only compile-time validation you have in the VBE for your code - consider reviewing Rubberduck inspections in that case (several inspections flag run-time error situations statically).
A better, more viable solution would be to reconsider the dependency chain and the overall approach.