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.