生成每个可能的VBA引用GUID的列表

我有一个Access数据库,我在Access 2016中创build。我有一些VBA代码需要在Access 2016中的一些库。大多数其他用户有不同的老年版本的Access。

例如,我需要运行代码的一个库是Microsoft Access 16.0 Object Library 。 许多用户正在运行Office 2013,它具有Microsoft Access 15.0 Object Library而不是16.0。

我需要以编程方式在运行VBA代码时添加此版本的库。 这将需要我知道我一直无法在网上find的GUID。 我研究过的所有其他领域告诉你如何得到你已经激活的库的GUID,但是这对我不起作用,因为我不能使用或罚款15.0库。

我怎样才能find这个库的GUID和其他库我没有活动或安装?

安装15.0时以编程方式添加16.0可能只会导致更多的崩溃,并不会解决您的问题。

早期绑定的代码(即带有对types库的项目引用)是特定于版本的,这意味着如果用户正在运行不同的版本,则可能会出现问题。

后期绑定的代码(即没有对types库的项目引用)不是特定于版本的:如果用户正在运行不同的版本,则后期绑定的调用将在运行时parsing为存在于无论你的用户运行什么版本。 如果存在

最后一点是关键:如果你的代码使用只存在于16.0库中的function,那么你可以期待运行时错误438“对象不支持这个属性或方法”抛在你的用户面上。 因此, 编写代码以便它可以在最低的可用版本上运行 。

如果您不知道版本之间有哪些API差异,那么您唯一的希望就是使用用户的最早版本进行开发 。


用早期的声明和调用你的代码; 这样你可以获得智能感知和自动完成function,你可以浏览对象浏览器 (F2)来探索可用的function。

避免使用types库中存在的枚举和常量:声明自己的属性,并复制基础值( 对象浏览器非常适合)。 一旦你切换到后期绑定的代码,这些枚举和常量将不再被定义,除非你自己定义它们。 确保指定了Option Explicit ,这样如果你碰巧在某个地方忘记了某个地方,就会得到一个编译时错误,而不是在运行时静静地传递一个错误的值,并且遇到奇怪的,难以debugging的行为。

当您准备好部署时,注释掉所有Dim accApp As Access.Application和其他早期的声明; 用Dim accApp As ObjectObject是什么使得调用在运行时被延迟/parsing)。

然后使用CreateObject调用replace所有Set foo = New XYZ赋值,例如Set accApp = New Access.Application将被Set accApp = CreateObject("Access.Application") 。 这是什么指示运行时去registry来找出该ProgID的types库可能在哪里。 如果用户的机器上没有ProgID,事情就会在运行时炸毁。


至于所问的问题, Ross Knudsen的Kavod.ComReflection GitHub存储库包含一些线索:

 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; } } } 

如果您确实想获取所有注册types库及其各自的GUID列表,则需要扫描Windowsregistry的ClassesRoot节点并find所有TypeLib子项。 这在VBA中实现起来可能相当有趣,但IMO对于你所要做的事情不是很有用。

除非您的计算机上安装了Office 2013,否则您将无法访问Microsoft Access 15.0 Object Library 。 同样,除非您的用户安装了Office 2016,否则他们将无法访问Microsoft Access 16.0 Object Library 。 但是,如果您拥有Office 2016,则引用Microsoft Access 15.0 Object Library vba代码仍然可以工作。

所以正如我在评论中所说的,当涉及到Office时,您需要以最低的共同点开发您的vba 。 即如果你最早的Access版本是2010,那么你需要在2010年开发。

此外, 14.0 Object Library将工作15.0 Object Library将适用于16.0 Object Library等,而不是反过来。 所以,如您所见,如果您在Office 2010中开发了某些function,则应该在2016年仍能正常工作。至less,您不应该有任何库参考问题。

警告编辑

只记得我试图debugging一些代码的时候真棒 。 如果您在Office 2013中开发并保存macros文档,然后使用Office 2016更改文档并保存,Office将自动select它认为Object Library的正确版本为16.0 。 这将使macros文档对您的Office 2013用户无用

一个简单的解决scheme(但可能不是你正在寻找的),就是先像你一样开发它,然后在部署之前,将这些声明转换为CreateObject调用。

像这样的东西:

 ' Normal way Dim A As Excel.Worksheet ' With CreateObject Dim B As Object Set B = CreateObject("Excel.Worksheet") 

对这样的代码进行故障排除是非常痛苦的,所以请保持旧的声明。