Cómo agregar una referencia mediante programación

89

Escribí un programa que se ejecuta y envía mensajes a Skype con información cuando termina. Necesito agregar una referencia para Skype4COM.dllpoder enviar un mensaje a través de Skype. Tenemos una docena de computadoras en una red y un servidor de archivos compartidos (entre otras cosas). Todas las demás computadoras deben poder ejecutar este programa. Esperaba evitar configurar la referencia a mano. Había planeado poner la referencia en una ubicación compartida y agregarla programáticamente cuando se ejecutara el programa.

Parece que no puedo averiguar cómo agregar una referencia mediante programación a Excel 2007 usando VBA. Sé cómo hacerlo manualmente: Abrir VBE --> Tools --> References --> browse --_> File Location and Name. Pero eso no es muy útil para mis propósitos. Sé que hay formas de hacerlo en Access Vb.net y un código similar a este seguía apareciendo, pero no estoy seguro de entenderlo, o si es relevante:

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

Hasta ahora, en las soluciones presentadas, para agregar la referencia programáticamente, tendré que agregar una referencia a mano y cambiar el Centro de confianza, que es más que simplemente agregar la referencia. Aunque supongo que si sigo adelante con las soluciones propuestas, podré agregar referencias futuras mediante programación. Lo que probablemente hace que valga la pena el esfuerzo.

Cualquier otro pensamiento sería genial.

Ommit
fuente
2
puede usar CreateObject () sin agregar una referencia en Excel 2010
Qbik
1
No tengo idea de por qué esto ha cobrado vida nuevamente, pero eche un vistazo a la vinculación temprana / tardía. Si agrega una referencia (ya sea a mano o mediante programación), vincula su código a una versión específica. por ejemplo, la biblioteca de Excel 11 está vinculada a Excel 2003. Todo bien si eso es lo que quieres, pero con bastante frecuencia (especialmente donde trabajo) necesito que funcione en 2003, 2007 y 2010.
Darren Bartrup-Cook

Respuestas:

110

Ommit

Hay dos formas de agregar referencias a través de VBA a sus proyectos

1) Usando GUID

2) Hacer referencia directa a la dll.

Déjame cubrir ambos.

Pero primero, estas son 3 cosas de las que debes cuidar

a) Las macros deben estar habilitadas

b) En la configuración de seguridad, asegúrese de que "Confiar en el acceso al proyecto de Visual Basic" esté marcado

ingrese la descripción de la imagen aquí

c) Ha establecido manualmente una referencia al objeto "Microsoft Visual Basic para Extensibilidad de Aplicaciones"

ingrese la descripción de la imagen aquí

Forma 1 (usando GUID)

Normalmente evito esta forma porque tengo que buscar el GUID en el registro ... lo cual odio LOL. Más sobre GUID aquí .

Tema: Agregar una biblioteca de referencia de VBA mediante código

Enlace : 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

Forma 2 (referencia directa a la dll)

Este código agrega una referencia a 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

Nota : No he agregado Manejo de errores. Se recomienda que en su código real, lo use :)

EDITAR Batido por mischab1:)

Huida de Siddharth
fuente
2
Entonces, ¿parece que en lugar de agregar la referencia a mano, necesito agregar una referencia separada a mano y cambiar los permisos de Excel? De acuerdo, será mejor en el futuro, pero ahora parece un poco divertido.
Ommit
2
Sí, suena divertido, pero así es en este momento :)
Siddharth Rout
1
Gran respuesta. Para su información, los usuarios de esto, noten que todavía no pueden usar ningún Word / PowerPoint / otro objeto o Enum fuera de una función o procedimiento con esto, ya que el compilador fallará antes de que el WORKBOOK_OPENevento comience a ejecutarse. Por lo tanto, no puede crear un objeto Public Word y no puede definir el tipo de un parámetro como un tipo Word / PPT (por ejemplo, no puede hacer algo así Sub CopyActiveChartToWord(FormatType as WdPasteDataType)).
s_a
3
¿No serán diferentes las ubicaciones de las carpetas de algunas DLL en las diferentes versiones de Windows? (por ejemplo, Win 8, Win 7, Vista, XP, etc.). En cuyo caso, ¿no será más seguro agregar mediante GUID (si sus usuarios tienen diferentes versiones de Win)?
Johnny Why
10
Para el registro, el GUID para MS Scripting Runtime es {420B2830-E718-11CF-893D-00A0C9054228}. Puede encontrar otros GUID agregándolos manualmente, luego recorriendo cada uno Ref ThisWorkbook.VBProject.Referencesy usandoDebug.Print Ref.Name, Ref.Guid
airstrike
26

Hay dos formas de agregar referencias usando VBA. .AddFromGuid(Guid, Major, Minor)y .AddFromFile(Filename). Cuál es el mejor depende de a qué intente agregar una referencia. Casi siempre lo uso .AddFromFileporque las cosas a las que me refiero son otros proyectos de Excel VBA y no están en el Registro de Windows.

El código de ejemplo que está mostrando agregará una referencia al libro de trabajo en el que se encuentra el código. Por lo general, no veo ningún sentido en hacerlo porque el 90% de las veces, antes de que pueda agregar la referencia, el código ya no se pudo compilar porque falta la referencia. (Y si no se pudo compilar, probablemente esté utilizando un enlace tardío y no necesita agregar una referencia).

Si tiene problemas para ejecutar el código, existen dos posibles problemas.

  1. Para utilizar fácilmente el modelo de objetos de VBE, debe agregar una referencia a Microsoft Visual Basic para la extensibilidad de la aplicación . (VBIDE)
  2. Para ejecutar el código VBA de Excel que cambia algo en un VBProject, debe confiar en el acceso al modelo de objetos del proyecto VBA . (En Excel 2010, se encuentra en el Centro de confianza - Configuración de macros).

Aparte de eso, si puede ser un poco más claro sobre cuál es su pregunta o qué está tratando de hacer que no funciona, podría darle una respuesta más específica.

mischab1
fuente
10

Examinar el registro en busca de guías o utilizar rutas, cuál es el mejor método. Si ya no es necesario navegar por el registro, ¿no será la mejor forma de utilizar las guías? Office no siempre se instala en el mismo directorio. La ruta de instalación se puede modificar manualmente. Además, el número de versión es parte de la ruta. Nunca podría haber predicho que Microsoft agregaría '(x86)' a 'Archivos de programa' antes de la introducción de los procesadores de 64 bits. Si es posible, trataría de evitar usar una ruta.

El siguiente código se deriva de la respuesta de Siddharth Rout, con una función adicional para enumerar todas las referencias que se utilizan en el libro de trabajo activo. ¿Qué sucede si abro mi libro en una versión posterior de Excel? ¿Seguirá funcionando el libro sin adaptar el código VBA? Ya he comprobado que las guías para Office 2003 y 2010 son idénticas. Esperemos que Microsoft no cambie las guías en versiones futuras.

Los argumentos 0,0 (de .AddFromGuid) deberían usar la última versión de una referencia (que no he podido probar).

¿Cuáles son tus pensamientos? Por supuesto que no podemos predecir el futuro, pero ¿qué podemos hacer para que la versión de nuestro código sea a prueba?

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

El código anterior ya no necesita la referencia al objeto "Microsoft Visual Basic para Extensibilidad de Aplicaciones".

Hennep
fuente
3
Tenga en cuenta que debe tener las macros habilitadas y la opción Trust Access To Visual Basic Project marcada (puntos ayb en la respuesta de @Siddharth_Rout), ¡pero +1 para eliminar la referencia de VBIDE! Además, aprecio que DebugPrintExistingRefs lo genera en el formato para copiar y pegar la línea en el código.
GlennFromIowa
7

¡Aquí se explica cómo obtener el Guid mediante programación! ¡Luego puede usar estas guías / rutas de archivo con una respuesta anterior para agregar la referencia!

Referencia: 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

Aquí está el mismo código pero imprimiendo en la terminal si no desea dedicar una hoja de trabajo a la salida.

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 
Chad Crowe
fuente