PDA

View Full Version : Solved: Adding reference via code



MacroShadow
03-27-2012, 03:52 AM
How can I check if there is a reference for "Microsoft Visual Basic for Applications Extensibility 5.3" set in my project, and if it's not referenced add a reference.

I have successfully added references via vba given that Microsoft Visual Basic for Applications Extensibility 5.3 is referenced, using the following code:

Sub AddRef()

Dim VBAEditor As VBIDE.VBE
Dim vbProj As VBIDE.VBProject
Dim chkRef As Reference
Dim BoolExists As Boolean

Set VBAEditor = Application.VBE
Set vbProj = ActiveDocument.VBProject

'~~> Check if "Microsoft VBScript Regular Expressions 5.5" is already added
For Each chkRef In vbProj.References
If chkRef.Name = "VBScript_RegExp_55" Then
BoolExists = True
GoTo grep
End If
Next

vbProj.References.AddFromFile "C:\WINDOWS\system32\vbscript.dll\3"

End Sub

defcon_3
03-27-2012, 06:04 PM
Simply check on the reference if its checked or not. :)
Are you sure the code work, coz it giving me error?

MacroShadow
03-27-2012, 07:19 PM
Ok, I should have been more specific, I need to check via code if the reference exists.

What error are you getting? If it's a compile error : "Function or interface marked as restricted, or the function uses a Automation type not supported in Visual Basic." you most probably put the code in "This Document", it must be in a module. I just discovered this now.

fumei
03-27-2012, 09:22 PM
How can I check if there is a reference for "Microsoft Visual Basic for Applications Extensibility 5.3" set in my project, and if it's not referenced add a reference.No real need to check. With the code below, if it is already there, nothing happens (the code exits). If it is not there, it is added.Sub AddRef()
Dim chkRef
For Each chkRef In ActiveDocument.VBProject.References
If chkRef.Name = "VBIDE" Then
Exit Sub
End If
Next
ActiveDocument.VBProject.References.AddFromFile _
"C:\Program Files (x86)\Common Files\microsoft shared\VBA\VBA6\VBE6EXT.olb"
End Sub

Make sure you have the proper path to the library for your machine.

Note that if you do NOT have Extensibility added, you can use it - like declaring a variable as VBIDE.VBProject, or even use Reference. But you CAN use ActiveDocument.VBProject.References IF you use a Variant.

MacroShadow
03-27-2012, 11:59 PM
fumei,

Thank you, that's just what I needed.
Although there seems to be one caveat, if the following sub exists in the same module (even if the sub has no body) and Extensibility reference does not exist, it will throw a "compile error: User-Defined type not defined" when your AddRef sub is ran and highlight in blue the name of the sub (Sub AddReferences(ByRef myProj As VBProject), not including the closing parenthesis), strangely enough when the project is compiled from the debug menu nothing happens.

Sub AddReferences(ByRef myProj As VBProject)

End Sub

fumei
03-28-2012, 12:27 AM
VBA parses all procedures in any given module. So, obviously, if there is an invalid object - VBProject in the Sub - it is, well, invalid, as long as Extensibility is not an added reference.

What do you mean by: "when the project is compiled from the debug menu"???

How do you compile the project (as opposed to any given procedure)?

MacroShadow
03-28-2012, 12:42 AM
What do you mean by: "when the project is compiled from the debug menu"???

How do you compile the project (as opposed to any given procedure)?

In the VBE --> Debug --> Compile XXXX

Frosty
03-28-2012, 06:23 AM
VBA compiles an entire module at run-time of any procedure within the module.

So you can have an uncompilable project with an uncompilable module... but if you had a separate module and ran routines *only* from it... you would not get any run-time compile errors.

MacroShadow
03-28-2012, 09:37 AM
But won't VBE --> Debug --> Compile XXXX compile the entire project (i.e. all modules)?

Frosty
03-28-2012, 09:51 AM
Yes, it will. And I use it all the time, I'm just giving additional information.

I would say it's best practice to use conditional compile statements like #IF...#Else...#End If so that you can compile your entire project, even in environments where your project would not compile.

However, it has been a practice not to use conditional compilation, but simply put "uncompilable" code into a separate module... and then only call that code in some circumstances (like when it wouldn't cause a run-time error).

For example, if you were writing code in a Word 2000 environment, but wanted to set certain options for when bits of code were run in a Word 2003 environment-- you might put all of that particular code in a separate module.

Just adding to your understanding of how and why compilation works. Especially when you're trying to add references in a programmatic way.

Frosty
03-28-2012, 09:56 AM
As an additional bit of information... you don't necessarily need to have project references in order to write code. You just have to not reference objects which aren't referenced. So you could compile your project if your dim statement was
Dim vbProj as Object (or Variant, depending on version of Word and some other factors like .NET versions)

And then your code would run even without the Extensibility reference added to your project.

This somewhat falls under the concept of Late-Binding vs. Early Binding.

Early-binding, in general, is preferred... but there are times when Late-Binding is useful.

MacroShadow
03-28-2012, 10:19 AM
Frosty,

Thanks for the info, I found it very helpful:)


As an additional bit of information... you don't necessarily need to have project references in order to write code. You just have to not reference objects which aren't referenced. So you could compile your project if your dim statement was
Dim vbProj as Object (or Variant, depending on version of Word and some other factors like .NET versions)

And then your code would run even without the Extensibility reference added to your project.

This somewhat falls under the concept of Late-Binding vs. Early Binding.

Early-binding, in general, is preferred... but there are times when Late-Binding is useful.

That seems to expound on fumei's post (#4)


But you CAN use ActiveDocument.VBProject.References IF you use a Variant.

Frosty
03-28-2012, 10:38 AM
Sure thing... and also, Compile doesn't catch all errors which are technically compile errors but manifest as run-time errors. This concept also falls into the early-binding/late-binding stuff.

Getting to know your "locals" and "watch" windows in the VDE will greatly help your understanding (since I'm guessing, just by the nature of this post, that you already have at least a rudimentary understanding of some of the programming concepts).

But, back to the original thing... is this issue solved for you now?

fumei
03-28-2012, 10:42 AM
But won't VBE --> Debug --> Compile XXXX compile the entire project (i.e. all modules)?

Yes, it will. And I use it all the time

To what end?

Manually compiling (via Debug) is only useful if you have very large projects. If your project is only 300 lines of code (say) there is no real point in using Debug > Compile. VBA compiles automatically when you execute. Yes, Compile generates p-code but again there is no discernable advantage unless it is a very large project.

Yes, it does check for errors, but again using Run (when you test) does the same thing.

As an additional bit of information... you don't necessarily need to have project references in order to write code. You just have to not reference objects which aren't referenced. So you could compile your project if your dim statement was
Dim vbProj as Object (or Variant, depending on version of Word and some other factors like .NET versions)

And then your code would run even without the Extensibility reference added to your project.
That is why I posted: "But you CAN use ActiveDocument.VBProject.References IF you use a Variant.`

Sub AddRef()
Dim chkRef
For Each chkRef In ActiveDocument.VBProject.References

MacroShadow
03-28-2012, 11:17 AM
But, back to the original thing... is this issue solved for you now?
I still don't understand why
Sub AddReferences(ByRef myProj As VBProject)

End Sub won't compile.

Frosty
03-28-2012, 12:05 PM
Fumei:

I don't know about you, but the majority of projects I work on have a lot of code. It is my habit to regularly compile and save my project, to make sure I didn't make a mistake before I distribute code to my end-users.

MacroShadow:
The reason it doesn't compile is because you have no project reference to the Extensibility library... so while VBProject is an accessible PROPERTY of a Document Object, it is not an object you can explicitly create a variable (or parameter) for, without a project reference to the Extensibility object.

That probably seems obtuse... but I would do some research on late-binding vs. early-binding concepts to help your understanding.

MacroShadow
03-28-2012, 12:11 PM
Thanks. Case closed. Issue resolved. Matter understood...

Frosty
03-28-2012, 12:12 PM
As an example...

Sub Test()
Dim o As Variant
Set o = ActiveDocument.VBProject
AddReferences o
End Sub
Sub AddReferences(ByRef myProj As Variant)
Stop
End Sub
Run the routine Test.
Your code will stop within the AddReferences subroutine.

Now view your Locals window (VDE > View > Locals Window)
You will see "myProj" as something you can expand. Expand it.

You will see various properties of that Object. You will also see, under the Type column of the locals window, that it is defined as a Variant/Object/VBProject (at least, in Word 2010).

In Word 2003, you will see the type defined as a Object/VBProject.

Without getting too deep into it, the newer versions of Word are using more .NET components, which can "coerce" (a term you might want to look up) Variants and Objects more interchangeably than earlier versions of Word (when Variants and Objects didn't work together very well).

The reason you would want to add the Extensibility reference to your project is not so that your project *could* work... but so that it would be easier to program and avoid run-time errors.

Technically, you don't have to use Option Explicit or dimension variables at all. But what you're doing when you do that is forcing VBA to figure out the appropriate data type to use when it is time to use it. This can cause a lot of run-time errors (try setting an object to a value of "Hello") which would be avoided during "design time" by proper variable typing.

MacroShadow
03-28-2012, 12:55 PM
Thanks.