102

I've written a program that runs and messages Skype with information when if finishes. I need to add a reference for Skype4COM.dll in order to send a message through Skype. We have a dozen or so computers on a network and a shared file server (among other things). All of the other computers need to be able to run this program. I was hoping to avoid setting up the reference by hand. I had planned on putting the reference in a shared location, and adding it programmatically when the program ran.

I can't seem to figure out how to add a reference programmatically to Excel 2007 using VBA. I know how to do it manually: Open VBE --> Tools --> References --> browse --_> File Location and Name. But that's not very useful for my purposes. I know there are ways to do it in Access Vb.net and code similar to this kept popping up, but I'm not sure I understand it, or if it's relevant:

ThisWorkbook.VBProject.References.AddFromGuid _
    GUID:="{0002E157-0000-0000-C000-000000000046}", _
    Major:=5, Minor:=3

So far, in the solutions presented, in order to add the reference programmatically I will need to add a reference by hand and change the Trust Center - which is more than just adding the reference. Though I guess if I follow through with the solutions proposed I will be able to add future references programmatically. Which probably makes it worth the effort.

Any further thoughts would be great.

abu
  • 422
  • 7
  • 14
Ommit
  • 1,894
  • 5
  • 19
  • 26
  • 3
    you can use CreateObject() without adding reference under Excel 2010 – Qbik Dec 19 '14 at 15:44
  • 2
    No idea why this has come alive again - but have a look at early/late binding. If you add a reference (either by hand or programmatically) it ties your code to a specific version. e.g. Excel 11 library is tied to Excel 2003. All good if that's what you want, but quite often (especially where I work) I need it to work on 2003, 2007 and 2010. – Darren Bartrup-Cook Jul 15 '15 at 11:01

4 Answers4

123

Ommit

There are two ways to add references via VBA to your projects

1) Using GUID

2) Directly referencing the dll.

Let me cover both.

But first these are 3 things you need to take care of

a) Macros should be enabled

b) In Security settings, ensure that "Trust Access To Visual Basic Project" is checked

enter image description here

c) You have manually set a reference to `Microsoft Visual Basic for Applications Extensibility" object

enter image description here

Way 1 (Using GUID)

I usually avoid this way as I have to search for the GUID in the registry... which I hate LOL. More on GUID here.

Topic: Add a VBA Reference Library via code

Link: http://www.vbaexpress.com/kb/getarticle.php?kb_id=267

'Credits: Ken Puls
Sub AddReference()
     'Macro purpose:  To add a reference to the project using the GUID for the
     'reference library

    Dim strGUID As String, theRef As Variant, i As Long

     'Update the GUID you need below.
    strGUID = "{00020905-0000-0000-C000-000000000046}"

     'Set to continue in case of error
    On Error Resume Next

     'Remove any missing references
    For i = ThisWorkbook.VBProject.References.Count To 1 Step -1
        Set theRef = ThisWorkbook.VBProject.References.Item(i)
        If theRef.isbroken = True Then
            ThisWorkbook.VBProject.References.Remove theRef
        End If
    Next i

     'Clear any errors so that error trapping for GUID additions can be evaluated
    Err.Clear

     'Add the reference
    ThisWorkbook.VBProject.References.AddFromGuid _
    GUID:=strGUID, Major:=1, Minor:=0

     'If an error was encountered, inform the user
    Select Case Err.Number
    Case Is = 32813
         'Reference already in use.  No action necessary
    Case Is = vbNullString
         'Reference added without issue
    Case Else
         'An unknown error was encountered, so alert the user
        MsgBox "A problem was encountered trying to" & vbNewLine _
        & "add or remove a reference in this file" & vbNewLine & "Please check the " _
        & "references in your VBA project!", vbCritical + vbOKOnly, "Error!"
    End Select
    On Error GoTo 0
End Sub

Way 2 (Directly referencing the dll)

This code adds a reference to Microsoft VBScript Regular Expressions 5.5

Option Explicit

Sub AddReference()
    Dim VBAEditor As VBIDE.VBE
    Dim vbProj As VBIDE.VBProject
    Dim chkRef As VBIDE.Reference
    Dim BoolExists As Boolean

    Set VBAEditor = Application.VBE
    Set vbProj = ActiveWorkbook.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 CleanUp
        End If
    Next

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

CleanUp:
    If BoolExists = True Then
        MsgBox "Reference already exists"
    Else
        MsgBox "Reference Added Successfully"
    End If

    Set vbProj = Nothing
    Set VBAEditor = Nothing
End Sub

Note: I have not added Error Handling. It is recommended that in your actual code, do use it :)

EDIT Beaten by mischab1 :)

Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
  • 2
    So it seems that instead of adding the reference by hand I need to add a separate reference by hand and change excel permissions? Granted it will be better in the future, but it seems a little funny now. – Ommit Mar 27 '12 at 20:09
  • 2
    Yes it does sound funny but then that's how it is at the moment :) – Siddharth Rout Mar 27 '12 at 20:25
  • 1
    Great answer. FYI users of this, notice that you still can't use any Word/PowerPoint/other object or Enum outside of a function or procedure with this since the compiler will fail before the `WORKBOOK_OPEN` event begins executing. So you can't create a Public Word object and you can't define the type of a parameter as a Word/PPT type (eg you can't do something like `Sub CopyActiveChartToWord(FormatType as WdPasteDataType)`). – s_a Apr 07 '14 at 16:28
  • 4
    Won't the folder locations of some DLL's be different in different versions of Windows? (eg Win 8, Win 7, Vista, XP, etc). In which case, won't adding by GUID be safer (if your users are on different Win versions)? – johny why Jul 06 '14 at 21:17
  • 1
    Change `Dim chkRef As Reference` to `Dim chkRef As VBIDE.Reference` – petter Sep 28 '14 at 15:48
  • Hmm.. So if I want to add a reference to "Microsoft Visual Basic for Applications Extensibility" programmatically am I SOL? – JMG Jan 10 '15 at 22:21
  • 14
    For the record, the GUID for MS Scripting Runtime is `{420B2830-E718-11CF-893D-00A0C9054228}`. You can find out other GUIDs by adding them manually, then looping through each `Ref` `ThisWorkbook.VBProject.References` and using `Debug.Print Ref.Name, Ref.Guid` – airstrike Sep 23 '16 at 19:50
  • 1
    Why you use `\3` at the final of the path ? – rvcristiand Jun 23 '18 at 16:28
  • Why you don't set chkRef = Nothing, is not necessary ? – rvcristiand Jun 23 '18 at 17:01
  • 1
    Manually enabling a reference to Microsoft Visual Basic for Applications Extensibility does not seem needed according to this question: https://stackoverflow.com/questions/10730300/connect-references-toolsreferences-with-vba-code-macros – Orbit Jul 14 '20 at 20:03
  • 1
    It's worth noting that `Major:=` and `Minor:=` arguments shouldn't be set to 1 and 0. It seems that usually in such cases VBA installs the latest version but some libraries have the same GUID but different `Major` and `Minor`. This is the case of `Microsoft VBScript Regular Expressions 5.5`. Both this library and its previous version - `Microsoft VBScript Regular Expressions 1.0` share the same GUID - `{3F4DACA7-160D-11D2-A8E9-00104B365C9F}` so `Major` and `Minor` have to be explicitly specified in order to install desired version. Tested on Excel 2016. – Soren V. Raben Aug 09 '22 at 10:38
29

There are two ways to add references using VBA. .AddFromGuid(Guid, Major, Minor) and .AddFromFile(Filename). Which one is best depends on what you are trying to add a reference to. I almost always use .AddFromFile because the things I am referencing are other Excel VBA Projects and they aren't in the Windows Registry.

The example code you are showing will add a reference to the workbook the code is in. I generally don't see any point in doing that because 90% of the time, before you can add the reference, the code has already failed to compile because the reference is missing. (And if it didn't fail-to-compile, you are probably using late binding and you don't need to add a reference.)

If you are having problems getting the code to run, there are two possible issues.

  1. In order to easily use the VBE's object model, you need to add a reference to Microsoft Visual Basic for Application Extensibility. (VBIDE)
  2. In order to run Excel VBA code that changes anything in a VBProject, you need to Trust access to the VBA Project Object Model. (In Excel 2010, it is located in the Trust Center - Macro Settings.)

Aside from that, if you can be a little more clear on what your question is or what you are trying to do that isn't working, I could give a more specific answer.

mischab1
  • 1,581
  • 12
  • 17
17

Browsing the registry for guids or using paths, which method is best. If browsing the registry is no longer necessary, won't it be the better way to use guids? Office is not always installed in the same directory. The installation path can be manually altered. Also the version number is a part of the path. I could have never predicted that Microsoft would ever add '(x86)' to 'Program Files' before the introduction of 64 bits processors. If possible I would try to avoid using a path.

The code below is derived from Siddharth Rout's answer, with an additional function to list all the references that are used in the active workbook. What if I open my workbook in a later version of Excel? Will the workbook still work without adapting the VBA code? I have already checked that the guids for office 2003 and 2010 are identical. Let's hope that Microsoft doesn't change guids in future versions.

The arguments 0,0 (from .AddFromGuid) should use the latest version of a reference (which I have not been able to test).

What are your thoughts? Of course we cannot predict the future but what can we do to make our code version proof?

Sub AddReferences(wbk As Workbook)
    ' Run DebugPrintExistingRefs in the immediate pane, to show guids of existing references
    AddRef wbk, "{00025E01-0000-0000-C000-000000000046}", "DAO"
    AddRef wbk, "{00020905-0000-0000-C000-000000000046}", "Word"
    AddRef wbk, "{91493440-5A91-11CF-8700-00AA0060263B}", "PowerPoint"
End Sub

Sub AddRef(wbk As Workbook, sGuid As String, sRefName As String)
    Dim i As Integer
    On Error GoTo EH
    With wbk.VBProject.References
        For i = 1 To .Count
            If .Item(i).Name = sRefName Then
               Exit For
            End If
        Next i
        If i > .Count Then
           .AddFromGuid sGuid, 0, 0 ' 0,0 should pick the latest version installed on the computer
        End If
    End With
EX: Exit Sub
EH: MsgBox "Error in 'AddRef'" & vbCrLf & vbCrLf & err.Description
    Resume EX
    Resume ' debug code
End Sub

Public Sub DebugPrintExistingRefs()
    Dim i As Integer
    With Application.ThisWorkbook.VBProject.References
        For i = 1 To .Count
            Debug.Print "    AddRef wbk, """ & .Item(i).GUID & """, """ & .Item(i).Name & """"
        Next i
    End With
End Sub

The code above does not need the reference to the "Microsoft Visual Basic for Applications Extensibility" object anymore.

===============
Edited 2023-06-17:
===============

I couldn't resist this challenge :-)
I've modified the code to supply version information to the AddRef Sub. The major and minor arguments are optional for backward compatibility.

I noticed that vbscript.dll is the only reference that reuses the guid amongst versions, I didn't find another one. Although Microsoft wrote in the documentation that version 0.0 will install the latest version, that appears not to work for VBScript v 5.5. Unfortunately I could not find that document again.
Like I said before, some things cannot be predicted.

In case the same guid from another version is already present, the Sub will ask conformation to replace the reference and display the full path of the removed reference in the immediate window:

AddRef thisworkbook, "{3F4DACA7-160D-11D2-A8E9-00104B365C9F}", "VBScript_RegExp_10", 1, 0       ' install v. 1.0  
The reference to C:\Windows\System32\vbscript.dll\3 was removed.  
  
AddRef thisworkbook, "{3F4DACA7-160D-11D2-A8E9-00104B365C9F}", "VBScript_RegExp_55", 5, 5       ' install v. 5.5  
The reference to C:\Windows\System32\vbscript.dll\2 was removed

And that again will fail for references of the same library with different guids. To avoid an error when, for instance, we want to add ADODB v. 6.1, and ADODB v. 2.8 is still present, we will need to remove 2.8 first.
For the "Microsoft ActiveX Object Library" I found 6 versions and all of these have a different guid. When I add a reference to anyone of them, and an other version is already present, an error is shown. To prevent that from happening we have to try to remove all older versions. Unfortunately we have to maintain the list of older references ourselves:

DelRef thisworkbook, "{00000200-0000-0010-8000-00AA006D2EA4}"                                   ' remove reference to ADODB v. 2.0
DelRef thisworkbook, "{00000201-0000-0010-8000-00AA006D2EA4}"                                   ' remove reference to ADODB v. 2.1
DelRef thisworkbook, "{00000205-0000-0010-8000-00AA006D2EA4}"                                   ' remove reference to ADODB v. 2.5
DelRef thisworkbook, "{00000206-0000-0010-8000-00AA006D2EA4}"                                   ' remove reference to ADODB v. 2.6
DelRef thisworkbook, "{EF53050B-882E-4776-B643-EDA472E8E3F2}"                                   ' remove reference to ADODB v. 2.7
DelRef thisworkbook, "{2A75196C-D9EB-4129-B803-931327F72D5C}"                                   ' remove reference to ADODB v. 2.8
AddRef thisworkbook, "{B691E011-1797-432E-907A-4D8C69339129}", "ADODB", 6, 1                    ' install v. 6.1

I modified "Sub AddRef" and added "Sub DelRef" and "Sub DebugPrintExistingRefsWithVersion"

Sub AddRef(wbk As Workbook, sGuid As String, sRefName As String, Optional varMajor As Variant, Optional varMinor As Variant)
    Dim i As Integer
    On Error GoTo EH
    With wbk.VBProject.References
        If IsMissing(varMajor) Or IsMissing(varMinor) Then
           For i = 1 To .Count
               If .Item(i).Name = sRefName Then
                  Exit For
               End If
           Next i
           If i > .Count Then
              .AddFromGuid sGuid, 0, 0 ' 0,0 should pick the latest version installed on the computer
           End If
        Else
           For i = 1 To .Count
               If .Item(i).Guid = sGuid Then
                  If .Item(i).Major = varMajor And .Item(i).Minor = varMinor Then
                     Exit For
                  Else
                     If vbYes = MsgBox(.Item(i).Name & " v. " & .Item(i).Major & "." & .Item(i).Minor & " is currently installed," & vbCrLf & "do you want to replace it with v. " & varMajor & "." & varMinor, vbQuestion + vbYesNo, "Reference already exists") Then
                        DelRef wbk, sGuid
                     Else
                        i = 0
                        Exit For
                     End If
                  End If
               End If
           Next i
           If i > .Count Then
              .AddFromGuid sGuid, varMajor, varMinor
           End If
        End If
    End With
EX: Exit Sub
EH: MsgBox "Error in 'AddRef' for guid:" & sGuid & " " & vbCrLf & vbCrLf & Err.Description
    Resume EX
    Resume ' debug code
End Sub

Public Sub DelRef(wbk As Workbook, sGuid As String)
    Dim oRef As Object
    For Each oRef In wbk.VBProject.References
        If oRef.Guid = sGuid Then
           Debug.Print "The reference to " & oRef.FullPath & " was removed."
           Call wbk.VBProject.References.Remove(oRef)
        End If
    Next
End Sub

Public Sub DebugPrintExistingRefsWithVersion()
    Dim i As Integer
    With Application.ThisWorkbook.VBProject.References
        For i = 1 To .Count
            Debug.Print "   'AddRef wbk, """ & .Item(i).Guid & """, """ & .Item(i).Name & """" & Space(30 - Len("" & .Item(i).Name)) & " ' install the latest version"
            Debug.Print "    AddRef wbk, """ & .Item(i).Guid & """, """ & .Item(i).Name & """, " & .Item(i).Major & ", " & .Item(i).Minor & Space(30 - Len(", " & .Item(i).Major & ", " & .Item(i).Minor) - Len("" & .Item(i).Name)) & " ' install v. " & .Item(i).Major & "." & .Item(i).Minor
        Next i
    End With
End Sub

Needles to say, I really don't like VBA references at all, I will try to avoid them when possible.

hennep
  • 545
  • 4
  • 12
  • 4
    Note that you do have to have macros enabled and Trust Access To Visual Basic Project checked (points a and b in [answer](https://stackoverflow.com/a/9880276/2712565) from @Siddharth_Rout), but +1 for eliminating the VBIDE reference! Also, I appreciate that DebugPrintExistingRefs outputs it in the format to copy and paste the line into code. – GlennFromIowa Oct 11 '17 at 16:57
  • 1
    I tested `Major:=0, Minor:=0` on Excel 2016 and it didn't work for `Microsoft VBScript Regular Expressions 5.5` - version 1.0 was added to references instead. – Soren V. Raben Aug 09 '22 at 10:41
  • Same problem here, but when I search for the CLSID with regedit.exe it shows 5.5 as the version when 1.0 is installed. Can you determine by the functionality what version is in use? I cannot help here, never used that reference. – hennep Aug 11 '22 at 12:14
  • 1
    I tested `Major:=0`, `Minor:=0` on MS Excel 2021 MSO v2301 b16.0.16026.20002 x32 bit and it didn't work for MSO Obj Lib with GUID {2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}: calling `wbk.VBProject.References.AddFromGuid strGUID, 0, 0` add a ref to MS VBE UI 7.1 Obj Lib with the same GUID but another dll! Correct should be (when I add manually the ref): "C:\Program Files (x86)\Common Files\Microsoft Shared\OFFICE16\MSO.DLL", but using my Sub VBA with maj 0, min 0, add a ref to: "C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7.1\VBEUI.DLL" – Emanuele Tinari Feb 11 '23 at 19:52
  • I've added functionality to supply major, minor arguments to AddRef – hennep Jun 17 '23 at 10:58
12

Here is how to get the Guid's programmatically! You can then use these guids/filepaths with an above answer to add the reference!

Reference: http://www.vbaexpress.com/kb/getarticle.php?kb_id=278

Sub ListReferencePaths()
'Lists path and GUID (Globally Unique Identifier) for each referenced library.
'Select a reference in Tools > References, then run this code to get GUID etc.
    Dim rw As Long, ref
    With ThisWorkbook.Sheets(1)
        .Cells.Clear
        rw = 1
        .Range("A" & rw & ":D" & rw) = Array("Reference","Version","GUID","Path")
        For Each ref In ThisWorkbook.VBProject.References
            rw = rw + 1
            .Range("A" & rw & ":D" & rw) = Array(ref.Description, _
                   "v." & ref.Major & "." & ref.Minor, ref.GUID, ref.FullPath)
        Next ref
        .Range("A:D").Columns.AutoFit
    End With
End Sub

Here is the same code but printing to the terminal if you don't want to dedicate a worksheet to the output.

Sub ListReferencePaths() 
 'Macro purpose:  To determine full path and Globally Unique Identifier (GUID)
 'to each referenced library.  Select the reference in the Tools\References
 'window, then run this code to get the information on the reference's library

On Error Resume Next 
Dim i As Long 

Debug.Print "Reference name" & " | " & "Full path to reference" & " | " & "Reference GUID" 

For i = 1 To ThisWorkbook.VBProject.References.Count 
  With ThisWorkbook.VBProject.References(i) 
    Debug.Print .Name & " | " & .FullPath  & " | " & .GUID 
  End With 
Next i 
On Error GoTo 0 
End Sub 
ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Chad Crowe
  • 1,260
  • 1
  • 16
  • 21