我有一个我在Access 2016中创建的Access数据库。我有一些VBA代码需要Access 2016中的一些库。大多数其他用户具有不同的旧版Access。
例如,我需要运行代码的一个库是Microsoft Access 16.0 Object Library
。许多用户正在运行Office 2013,其中Microsoft Access 15.0 Object Library
而不是16.0。
我需要在运行VBA代码时以编程方式添加此版本的库。这需要我知道GUID,我无法在网上找到。我研究过的所有其他领域都告诉你如何获得你活跃的图书馆的GUID,但这对我来说不会起作用,因为我不能使用或罚款15.0库。
如何找到此库的GUID,以及我没有活动或已安装的其他库?
答案 0 :(得分:6)
安装15.0时以编程方式添加16.0可能只会导致更多崩溃,并且无法解决您的问题。
早期绑定代码(即对类型库的项目引用)是特定于版本的,这意味着如果您的用户运行的是其他版本,则可能会出现问题。
后期绑定代码(即没有对类型库的项目引用)不是特定于版本的:如果您的用户运行的是其他版本,那么后期绑定的调用将会在运行时解析您的用户运行的任何版本中存在的适当方法。 如果存在。
最后一点是关键:如果您的代码使用仅存在于16.0库中的功能,那么您可以预期运行时错误438"对象不支持此属性或方法"被扔给你的用户'无论如何。因此,write your code so that it can run on the lowest available version。
如果您不知道版本之间存在什么API差异,那么您唯一的希望就是use the users' earliest version for development。
使用早期声明和调用来编写代码;这样您就可以获得IntelliSense和自动完成功能,并且可以浏览对象浏览器(F2)来探索可用的内容。
避免使用类型库中存在的枚举和常量:声明自己的枚举和常量,并复制基础值(对象浏览器非常适用于此)。一旦切换到后期绑定代码,这些枚举和常量将不再被定义,除非您自己定义它们。 确保指定了Option Explicit ,这样如果你碰巧忘了某个地方,你会得到一个编译时错误告诉它,而不是在运行时默默传递一个错误的值并且经历了奇怪的,难以调试的行为。
当您准备好部署时,请注释掉所有Dim accApp As Access.Application
和其他早期声明;替换为Dim accApp As Object
(Object
是在运行时进行后期绑定/解析的内容。)
然后使用Set foo = New XYZ
个来电替换所有CreateObject
个分配,例如Set accApp = New Access.Application
将是Set accApp = CreateObject("Access.Application")
。这是指示运行时命中注册表以确定该ProgID的类型库可能位于何处的内容。如果用户机器上没有该ProgID,那么在运行时会出现问题。
关于问题,Ross Knudsen's Kavod.ComReflection GitHub repository包含一些线索:
private static IEnumerable<ComTypeRegistryEntry> GetComTypeRegistryEntries() { using (var clsidRootKey = Registry.ClassesRoot.OpenSubKey("TypeLib")) { if (clsidRootKey == null) { yield break; } foreach (var typeLibKey in EnumerateSubKeys(clsidRootKey)) { var currentTypeLib = GetCurrentKeyName(typeLibKey); Guid clsid; if (!Guid.TryParseExact(currentTypeLib, "B", out clsid)) { Debug.WriteLine($"Couldn't parse CLSID = {currentTypeLib}"); continue; } foreach (var entry in EnumerateRegistryEntryVersions(typeLibKey, clsid)) yield return entry; } } }
如果确实想要获取所有已注册类型库及其各自GUID的列表,则需要扫描Windows注册表的ClassesRoot
节点并找到所有TypeLib
节点1}}子键。这在VBA中实现起来非常有趣,但IMO对你正在尝试做的事情并不是很有用。
答案 1 :(得分:3)
除非您的计算机上安装了Office 2013,否则您将无法访问Microsoft Access 15.0 Object Library
。同样,除非您的用户安装了Office 2016,否则他们将无法访问Microsoft Access 16.0 Object Library
。但是,如果您拥有Office 2016,则引用vba
的{{1}}代码仍然有效。
正如我在评论中所说,你需要在Office的最低标准中发展你的Microsoft Access 15.0 Object Library
。即如果您最早的Access版本是2010年,那么您需要在2010年开发。
此外,vba
适用于14.0 Object Library
适用于15.0 Object Library
等等,但不是相反。如您所见,如果您在Office 2010中开发了某些内容,那么应该仍然可以在2016年运行。至少,您不应该有任何库引用问题。
警告编辑
记得我在尝试调试某些代码时遇到的 awesome 时间。如果您在Office 2013中开发并保存宏文档,然后使用Office 2016更改文档并保存它,Office将自动选择它认为正确版本的16.0 Object Library
,将是Object Library
。这会将宏文档无用呈现给您的Office 2013用户。
答案 2 :(得分:1)
对此的一个简单解决方案(但可能不是您正在寻找的那个)是首先像您一样开发它,然后在部署之前,将声明转换为CreateObject调用。
这样的事情:
' Normal way
Dim A As Excel.Worksheet
' With CreateObject
Dim B As Object
Set B = CreateObject("Excel.Worksheet")
对像这样的代码进行故障排除是非常痛苦的,所以请将旧的声明保持在附近。