问题 以编程方式添加引用


我们有一个Access-Application,它不适用于某些客户端,主要是因为引用被破坏了。例如,当您使用访问运行时2007启动访问应用程序但安装了版本2003或2000的办公室时,就会发生这种情况。左/右/修剪等功能就此停止工作。

我认为解决这个问题的唯一方法是以编程方式检查安装了哪个办公室版本并以编程方式添加引用,因为在这些异构环境中我们无法控制用户安装的内容。具体来说,我需要引用Excel和Word的Microsoft Office对象库。

但我既没有所有办公室版本的指导,也没有线索如何自动检查它们。


10371
2018-04-08 10:09


起源

对Word和Excel使用后期绑定。然后你的问题就消失了。 - HansUp
如果你得到错误的Access库版本,即使内置函数停止工作,所以后期绑定也无济于事。但这只发生在同时安装了不同版本的计算机上。 - dwo


答案:


如果您发运MDE / ACCDE,则无法更新参考文献。

但具体的参考文献是什么导致你的问题?您有可能引用Word,Excel或Outlook。如果是这样,请使用后期绑定,因此您的解决方案与客户端系统上安装的版本无关。

延迟绑定意味着您可以安全地删除引用,并且只有在应用程序执行相关代码行时才会出错。而不是在启动应用程序时出错,而根本不允许应用程序中的用户。或者当遇到mid,left或trim函数调用时。

当您不知道外部应用程序的哪个版本将驻留在目标系统上时,这也非常有用。或者,如果您的组织正处于从一个版本移动到另一个版本的过程中。

有关更多信息,包括其他文字和一些详细链接,请参阅“Microsoft Access中的后期绑定“页面。


3
2018-04-08 16:41



但是,如果我创建Excel.Application对象,Excel将不会启动吗? - Falcon
你在用Excel做什么? - David-W-Fenton
Falcon,是的,Excel将在您创建对象后启动。但是,当您开始使用引用的Excel对象时会发生这种情况。 - Tony Toews
Tony ...我在假设我使用Late Binding是正确的,我必须为每个我自动化的Office App编写例程,每个应用程序版本都有不同的语法。例如,我拥有的应用程序是Access的非典型用例,因为我使用它来构建一个快速GUI,允许人们在现场自动执行ppt演示文稿,excel工作簿,Outlook电子邮件,xml数据文件,word文档等。因此,我必须为每个作业编写Word 2000,Word 2003,Word 2007的进程复制...以便使用后期绑定,并仍然保留功能? - Justin
不,您不需要为每个版本使用不同的语法。您编写的代码与使用引用的代码基本相同。唯一的区别是您不使用引用的外部库中的数据类型,并且您必须手动实例化外部应用程序的实例。否则,它是完全相同的代码。你为什么不尝试按照使用后期绑定的说明进行操作,看看它是如何工作的? - David-W-Fenton


所以,是的,这个答案有点晚了,但万一有人偶然发现这个问题,就像我一直在寻找答案一样,我想出了以下一些代码来添加一个excel引用,它似乎工作正常,同样在MDE / ACCDE!

If Dir("C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.exe") <> "" And Not refExists("excel") Then
    Access.References.AddFromFile ("C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.exe")
End If
If Dir("C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.exe") <> "" And Not refExists("excel") Then
    Access.References.AddFromFile ("C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.exe")
End If
If Dir("C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.exe") = "" And Dir("C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.exe") = "" Then
    MsgBox ("ERROR: Excel not found")
End If

refExists引用了以下函数:

Private Function refExists(naam As String)
Dim ref As Reference
refExists = False
For Each ref In References
    If ref.Name = naam Then
        refExists = True
    End If
Next
End Function

10
2017-09-12 09:31





下面是一个示例 - 它检查某些引用 - 删除它们并导入Access 2000变体。只是为了确保所有客户端使用相同(最低)版本的依赖项

Sub CheckReference()
' This refers to your VBA project.
    Dim chkRef As Reference ' A reference.

    Dim foundWord, foundExcel As Boolean

    foundWord = False
    foundExcel = False

    ' Check through the selected references in the References dialog box.
    For Each chkRef In References


        ' If the reference is broken, send the name to the Immediate Window.
        If chkRef.IsBroken Then
           Debug.Print chkRef.Name
        End If

        If InStr(UCase(chkRef.FullPath), UCase("MSWORD9.olb")) <> 0 Then
            foundWord = True
        End If

        If InStr(UCase(chkRef.FullPath), UCase("EXCEL9.OLB")) <> 0 Then
            foundExcel = True
        End If

        If InStr(UCase(chkRef.FullPath), UCase("MSWORD.olb")) <> 0 Then
            References.Remove chkRef
        ElseIf InStr(UCase(chkRef.FullPath), UCase("EXCEL.EXE")) <> 0 Then
            References.Remove chkRef
        End If


    Next

    If (foundWord = False) Then
        References.AddFromFile ("\\pathto\database\MSWORD9.OLB")
    End If

    If (foundExcel = False) Then
        References.AddFromFile ("\\pathto\database\EXCEL9.OLB")
    End If

End Sub

2
2018-04-08 11:10



我会投票通过修复参考资料来延迟绑定。 - David-W-Fenton
您无法修复MDE / ACCDE中的引用。 - Tony Toews
我不同意,上面的代码来自一个现场工作环境。 - Mark Mooibroek
这是来自MDE / ACCDE吗? - Tony Toews


这是一个代码示例,用于检查损坏的引用。我知道这不是适合你的整个解决方案,但它会为你提供一些如何做到这一点的线索。

Public Function CheckRefs()
    On Error GoTo Handler

    Dim rs As Recordset
    Dim ref As Reference
    Dim msg As String

    For Each ref In Application.References
        ' Check IsBroken property.
        If ref.IsBroken = True Then
            msg = msg & "Name: " & ref.Name & vbTab
            msg = msg & "FullPath: " & ref.FullPath & vbTab
            msg = msg & "Version: " & ref.Major & "." & ref.Minor & vbCrLf
        End If
    Next ref

    If Len(msg) > 0 Then MsgBox msg
    Exit Function

Handler:
    ' error codes 3075 and 3085 need special handling

    If Err.Number = 3075 Or Err.Number = 3085 Then
        Err.Clear
        FixUpRefs
    Else
        rs.Close
        Set rs = Nothing
    End If
End Function

Private Sub FixUpRefs()
    Dim r As Reference, r1 As Reference
    Dim s As String

    ' search the first ref which isn't Access or VBA
    For Each r In Application.References
        If r.Name <> "Access" And r.Name <> "VBA" Then
            Set r1 = r
            Exit For
        End If
    Next
    s = r1.FullPath

    ' remove the reference and add it again from file
    References.Remove r1
    References.AddFromFile s

    ' hidden syscmd to compile the db
    Call SysCmd(504, 16483)
End Sub

1
2018-04-08 10:53



在我的应用程序中,我完全避免这个问题,因为从不使用任何引用,除了默认的3,Access,VBA和DAO。在我看来,后期绑定真的是要走的路。 - David-W-Fenton
就个人而言,我同时做到了。在开发过程中,我使用引用进行类型检查并查看代码完成,然后切换到后期绑定。 - dwo
伙计,对。我的后期绑定页面提到了该技​​术以及示例代码,使切换更容易。 - Tony Toews
我可以设置一个足够长的引用来获取Intellisense,然后摆脱它。对于自动化Office应用程序,我甚至不再这样做 - 相反,我只是启动有问题的应用程序,打开它的VBE并使用本机Intellisense。 - David-W-Fenton
dwo,no Access不会自动删除缺少的引用。相反,在代码中的其他地方会出现奇怪的,难以理解的错误,例如在使用trim,left或mid等字符串函数时。 - Tony Toews