如何使用 VBA 以编程方式添加引用

Posted

技术标签:

【中文标题】如何使用 VBA 以编程方式添加引用【英文标题】:How to add a reference programmatically using VBA 【发布时间】:2012-04-10 09:51:55 【问题描述】:

我编写了一个程序,它运行并在完成时向 Skype 发送信息。我需要为 Skype4COM.dll 添加参考,以便通过 Skype 发送消息。我们在网络上有十几台计算机和一个共享文件服务器(除其他外)。所有其他计算机都需要能够运行该程序。我希望避免手动设置参考。我曾计划将引用放在一个共享位置,并在程序运行时以编程方式添加它。

我似乎无法弄清楚如何使用 VBA 以编程方式将引用添加到 Excel 2007。我知道如何手动操作:打开 VBE --> Tools --> References --> browse --_> File Location and Name。但这对我的目的不是很有用。我知道在Access Vb.net 中有一些方法可以做到这一点,并且类似的代码不断弹出,但我不确定我是否理解它,或者它是否相关:

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

到目前为止,在提供的解决方案中,为了以编程方式添加引用,我需要手动添加引用并更改信任中心 - 这不仅仅是添加引用。虽然我想如果我遵循提出的解决方案,我将能够以编程方式添加未来的参考。这可能值得付出努力。

任何进一步的想法都会很棒。

【问题讨论】:

在 Excel 2010 下可以使用 CreateObject() 而不添加引用 不知道为什么它又恢复了活力——但是看看早/晚绑定。如果您添加引用(手动或以编程方式),它会将您的代码绑定到特定版本。例如Excel 11 库与 Excel 2003 相关联。如果这是您想要的,那就太好了,但很多时候(尤其是在我工作的地方)我需要它在 2003、2007 和 2010 年工作。 【参考方案1】:

有两种方法可以使用 VBA 添加引用。 .AddFromGuid(Guid, Major, Minor).AddFromFile(Filename)。哪个最好取决于您要添加引用的内容。我几乎总是使用.AddFromFile,因为我引用的是其他 Excel VBA 项目,它们不在 Windows 注册表中。

您显示的示例代码将添加对代码所在工作簿的引用。我通常认为这样做没有任何意义,因为 90% 的时间,在您添加引用之前,代码已经由于缺少引用,编译失败。 (如果它没有编译失败,那么您可能正在使用后期绑定,并且您不需要添加引用。)

如果您在运行代码时遇到问题,可能有两个问题。

    为了轻松使用 VBE 的对象模型,您需要添加对Microsoft Visual Basic 应用程序扩展性的引用。 (VBIDE) 为了运行可以更改 VBProject 中任何内容的 Excel VBA 代码,您需要信任对 VBA 项目对象模型的访问。 (在 Excel 2010 中,它位于信任中心 - 宏设置中。)

除此之外,如果您可以更清楚地了解您的问题是什么,或者您尝试做什么但不起作用,我可以给出更具体的答案。

【讨论】:

【参考方案2】:

省略

有两种方法可以通过 VBA 将引用添加到您的项目中

1) 使用 GUID

2)直接引用dll。

让我两个都介绍一下。

但首先这是你需要注意的三件事

a)应该启用宏

b)在安全设置中,确保选中“信任对 Visual Basic 项目的访问”

c)您手动设置了对“Microsoft Visual Basic for Applications Extensibility”对象的引用

方式 1(使用 GUID)

我通常会避免这种方式,因为我必须在注册表中搜索 GUID……我讨厌 LOL。更多关于 GUID here.

主题:通过代码添加 VBA 参考库

链接: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

方式2(直接引用dll)

这段代码添加了对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

注意:我没有添加错误处理。建议在您的实际代码中使用它:)

编辑mischab1殴打:)

【讨论】:

所以看来我不需要手动添加引用,而是需要手动添加单独的引用并更改 excel 权限?诚然,未来会更好,但现在看来有点搞笑。 是的,听起来确实很有趣,但现在就是这样:) 很好的答案。仅供参考的用户请注意,您仍然不能在函数或过程之外使用任何 Word/PowerPoint/其他对象或枚举,因为编译器将在 WORKBOOK_OPEN 事件开始执行之前失败。所以你不能创建一个Public Word对象,你不能将参数的类型定义为Word/PPT类型(例如你不能做Sub CopyActiveChartToWord(FormatType as WdPasteDataType)之类的事情)。 在不同版本的windows下会不会有些DLL的文件夹位置不一样? (例如 Win 8、Win 7、Vista、XP 等)。在这种情况下,通过 GUID 添加会不会更安全(如果您的用户使用不同的 Win 版本)? 作为记录,MS Scripting Runtime 的 GUID 是 420B2830-E718-11CF-893D-00A0C9054228。您可以通过手动添加它们来找出其他 GUID,然后遍历每个 Ref ThisWorkbook.VBProject.References 并使用 Debug.Print Ref.Name, Ref.Guid【参考方案3】:

浏览注册表以获取 guid 或使用路径,哪种方法最好。如果不再需要浏览注册表,那么使用 guid 不是更好的方法吗? Office 并不总是安装在同一目录中。可以手动更改安装路径。版本号也是路径的一部分。 在引入 64 位处理器之前,我无法预料到微软会在“程序文件”中添加“(x86)”。 如果可能的话,我会尽量避免使用路径。

下面的代码源自 Siddharth Rout 的回答,具有一个附加功能,用于列出活动工作簿中使用的所有引用。 如果我在更高版本的 Excel 中打开我的工作簿怎么办?如果不调整 VBA 代码,工作簿仍然可以工作吗? 我已经检查过 Office 2003 和 2010 的指南是否相同。让我们希望微软在未来的版本中不要更改 guid。

参数 0,0(来自 .AddFromGuid)应该使用最新版本的引用(我无法测试)。

你的想法是什么?当然,我们无法预测未来,但我们能做些什么来证明我们的代码版本呢?

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

上面的代码不再需要对“Microsoft Visual Basic for Applications Extensibility”对象的引用。

【讨论】:

请注意,您必须启用宏并检查对 Visual Basic 项目的信任访问(@Siddharth_Rout 的answer 中的点 a 和 b),但 +1 用于消除 VBIDE 参考!另外,我很欣赏 DebugPrintExistingRefs 以格式输出它,以便将该行复制并粘贴到代码中。【参考方案4】:

以下是如何以编程方式获取 Guid!然后,您可以使用这些带有上述答案的 guid/文件路径来添加参考!

参考: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

这是相同的代码,但如果您不想将工作表专用于输出,则打印到终端。

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 

【讨论】:

以上是关于如何使用 VBA 以编程方式添加引用的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式将 .xlam 插件(作为对象)添加到 vba?

[Excel VBA]单元格区域引用方式的小结

Excel vba以编程方式将代码添加到工作表模块

如何在 VBA 中删除文本 - 以编程方式?

以编程方式从 Word 2007 文档中提取宏 (VBA) 代码

以编程方式打开受密码保护的 VBA 项目