Excel VBA Compile抛出“用户定义的类型未定义”错误,但不会转到违规行代码

时间:2013-10-30 11:00:32

标签: excel debugging vba excel-vba compiler-errors

症状

这是编译 Excel VBA项目时特有的症状。发生以下错误:

User-defined type not defined

但是,编译器不会突出显示产生此错误的代码,因此我无法确定问题。

我已经知道并尝试了

这是我之前看到的“用户定义的类型未定义”错误,其中包含命名As Strig而不是As String等简单问题。但是,此特定错误仅在Debug > Compile VBAProject菜单选项期间弹出,当弹出错误消息框时,它不会突出显示发生错误的代码行。

经过大量研究后,我发现这个bug可能与缺少的引用有关,我已经排除了这一点,因为我已经包含了所有需要的引用和Toolbox对象。

为确保我没有遗漏任何明显缺失的Dim语句,我已将Option Explicit添加到所有代码页(包含的表单)中,以确保没有遗漏任何内容。运行编译时仍会显示错误。

There is also this known bug表示已知问题会因为使用二进制兼容性的 VB6 项目而发生:

  

关闭二进制兼容性并编译项目。 Visual Basic   将突出显示包含用户定义类型的代码行   那是没有定义的。解决问题后,二进制兼容性   可以重新开启。

我通过此Question and Answer找到了这篇文章,但是,我在标准Excel VBA 编辑器中找不到此选项。

帮助拯救我和他人的理智!

我从Google搜索和其他问题中了解到,我并不是唯一一个遇到此问题的人。

我已尝试手动完成代码,但实际上只有太多行可行。

有没有办法在Excel VBA项目中关闭二进制兼容性?如果人们无法调试他们需要更改的内容,人们如何找到这个有问题的代码行?任何帮助都很可爱!

提前谢谢。

编辑: 我找到了令人讨厌的代码行,所以我的特定问题已经解决了删除该特定行后问题仍然存在 - 这是一个拼错控件在其代码中引用的表单上的名称。这仍然无法解决您如何找到这个有问题的代码的特定问题。当这个错误发生时,我们是否能够找到找到有问题的代码的好方法,以便将来的其他人可以避免这种痛苦?

21 个答案:

答案 0 :(得分:6)

我的解决方案不是好消息,但至少应该有效。

我的情况是:我有一个来自同事的.xlsm。 1)我打开它并单击按钮:它工作正常。 2)我保存文件,关闭excel,再次打开文件:现在它不再工作了。结论是:代码没问题但是excel无法正确管理引用。 (我尝试删除重新添加引用但没有成功)

因此,解决方案是将每个引用的对象声明为Variant并使用CreateObject("Foo.Bar")而不是New Foo.Bar

例如:

Dim objXML As MSXML2.DOMDocument
Set objXML = New MSXML2.DOMDocument

替换为:

Dim objXML As Variant
Set objXML = CreateObject("MSXML2.DOMDocument")

答案 1 :(得分:4)

因为听起来你已经尝试了许多不同的潜在解决方案,所以你现在可能必须采用这种方法来进行这种方法。

创建一个新的空白工作簿。然后一块一块地将旧工作簿复制到其中。添加引用,编写一些代码来测试它。确保它编译,确保它运行。添加一个子或函数,再次写一个小测试子来运行它,也确保它编译。重复此过程,慢慢添加并测试所有内容。

首先尝试更大的块可以加快速度,然后当找到触发问题的块时,将其移除并将其分解为较小的peices以进行测试。

要么你会找到罪犯,要么你会有一本神奇地没有问题的新工作簿。后者可能是由于工作簿文件中存在某种隐藏的损坏,可能是在二进制vbproject部分。

欢迎来到没有调试器或其他有用工具的调试世界,为您做繁重的工作!

答案 2 :(得分:2)

我遇到了完全相同的问题(当我尝试在用户窗体上实现接口时似乎总是会出现。从here下载并安装Code Cleaner。这是一个免费软件实用程序,它在很多场合保存了我。打开VBA项目后,运行"Clean Code..."选项。确保在运行clean之前检查“备份项目”和/或“导出所有代码模块”到安全位置。据我所知,这个实用程序导出然后重新导入所有模块和类,这消除了已经悄悄进入代码的编译器错误。对我来说就像一个魅力!祝你好运。

答案 3 :(得分:2)

让大家知道我也有这个问题。而不是代码,问题在于按钮调用的宏。 (它一直在调用'createroutes.createroutes'宏,但我已经将' createroutes'模块改名为'路线'。) 因此,通过将按钮指向正确的位置来解决问题。

答案 4 :(得分:2)

有一个类似的经历,但那是因为我在我的一个课程中重命名了一个enum。我导出并重新导入了引用旧枚举的类,错误消息消失了。这表明它是VBA环境中的缓存问题。

答案 5 :(得分:1)

我在普通的VB6程序中遇到了这个问题。原来我省略了一个类定义,而不是用户定义的类型。 VB显然看到了类似“Thing.name”的东西,并假设Thing是UDT。是的,这是一个严重的VB6错误,但你很难指望微软支持他们十六年前卖出的东西。那么您使用的各种产品的版本是什么?只有在MS支持的产品出现时才会感兴趣。

答案 6 :(得分:1)

我知道这已经过时了,但我遇到了类似的问题并找到了解决办法:

我将一个模块从Excel移植到Access中遇到了同样的问题,在一个不相关的UDF中,我调整了“As Range”,但Access中不存在范围。您可能在没有打开正确的参考库的情况下使用变量类型。

如果你有任何非标准的dims谷歌他们,看看你是否错过了工具下对该库的引用。

-E

答案 7 :(得分:1)

供将来参考 -

我在Microsoft Access中的这段代码遇到此问题,调试器突出显示注释行:

Option Compare Database
Option Explicit

Dim strSQL As String
Dim rstrSQL As String
Dim strTempPass As String


Private Sub btnForgotPassword_Click()
On Error GoTo ErrorHandler

Dim oApp As Outlook.Application '<---------------------------------Offending line
Dim oMail As MailItem
Set oApp = CreateObject("Outlook.application") 'this is the "instance" of Outlook
Set oMail = oApp.CreateItem(olMailItem) 'this is the actual "email"

我必须选择以前未选中的引用。他们是

Microsoft Outlook 15.0对象库
Microsoft Outlook视图控件

答案 8 :(得分:1)

可能的解决方案,您正尝试通过Excel VBA使用Powerpoint,并且您没有首先激活Powerpoint对象库。

要执行此操作,请在VBA编辑器顶部菜单中选择“工具”,“引用”,然后向下滚动以单击名为Microsoft Powerpoint xx.x对象库的库。 Office 2007是库12,每个Office版本都有不同的库。仅供参考,我在激活2007库时遇到了一些奇怪的错误和文件损坏,但有人试图使用Excel 2003打开并运行此宏。旧版本的Excel不能识别新的库,这似乎是引起问题。

答案 9 :(得分:1)

我能够通过

修复错误
  1. 完全关闭Access
  2. 重命名数据库文件
  3. 在Access中打开重命名的数据库文件。
  4. 接受各种安全警告和提示。
    • 我不仅选择启用宏,还接受将重命名的数据库设为可信文档。
    • 上一个文件也被标记为可信文档。
  5. 成功编译VBA项目时没有错误,没有更改代码。
  6. 成功编译后,我能够再次关闭Access,将其重命名为原始文件名。我不得不回复相同的安全提示,但是一旦我打开VBA项目,它仍然编译没有错误。
  7. 本案例和观察的一点历史:

    • 我发布这个答案是因为我观察到的症状与其他症状略有不同和/或我的解决方案看起来很独特。
    • 至少在我遇到错误的部分时间里,我的VBA窗口显示了两个额外的“神秘”项目。遗憾的是,在解决错误之前,我没有记录这些名字。一个像ACXTOOLS。里面的模块无法打开。
    • 我认为最初的问题确实是由于错误的代码,因为我在尝试更新其模块代码之前对表单进行了重大更改。但即使在修复代码之后,错误仍然存​​在。我知道代码有效,因为表单会加载而且没有错误。正如原始帖子所述,将出现“用户定义的类型未定义”错误,但不会出现任何有问题的代码行。
    • 在发现此错误之前,我确保添加了所有必要的参考。我不止一次地压缩和修复了数据库。我关闭了Access并在各种修复尝试之间多次重新打开文件。我删除了可疑的违规表格,但仍然收到错误。我尝试了在这里和其他论坛上建议的其他各种步骤,但没有解决问题。
    • 当我制作备份副本以尝试激烈的措施时,我偶然发现了这个问题,例如一次删除一个表单/模块。但是在打开备份副本时,问题并未再次发生。

答案 10 :(得分:1)

对于Scripting.Dictionary类型,您可以使用后期绑定(如已经指出的那样):

Dim Dict as Object
Set Dict = CreateObject("Scripting.Dictionary")

哪个有效,但是你没有得到代码自动完成。或者您使用早期绑定,但您需要确保VBA可以通过VBA添加对Microsoft Scripting Library的引用来找到Scripting.Dictionary类型 - &gt;工具 - &gt;参考 - &gt; “Microsoft Scripting Runtime”。然后你可以使用:

Dim Dict as Scripting.Dictionary
Set Dict = New Scripting.Dictionary

...并且自动完成功能正常。

答案 11 :(得分:0)

我有同样的问题,如果您启用Microsoft Scripting Runtime,您应该会很好。您可以在工具&gt;下执行此操作。参考&gt;然后选中 Microsoft Scripting Runtime 框。这应该可以解决您的问题。

答案 12 :(得分:0)

对于真正的错误或直接解决问题,我没有任何答案。

我可以报告导出所有代码和表单,然后将它们导入到新的工作簿中为我修复。所有工作都已恢复,无需做任何其他工作即可恢复工作。既然可以正常工作,显然它一定是Excel中的错误,否则新版本中仍然会丢失任何错误。

对于此Excel(2007)错误的工作方式,我确实有线索。它似乎与删除一个(或两个)类模块有关。 (但是由于某种原因,不是每次都使用每个类模块。)没有代码正在使用已删除模块的任何部分(否则新导入的版本也不起作用)。一个模块只剩下一些注释(希望删除以后可能“丢失”的所有内容),因此没有代码将其可视地连接到项目的任何其他部分。但是,在我完全删除代码模块后不久,出现了错误。返回已移除(但以防万一导出)模块时,错误也停止了。因此,为方便起见,该项目打包了两个未使用的代码模块,以避免出现此错误。

然后看来,即使在项目中的任何位置(这些类中有两个)中没有使用任何模块,某些脱离模块的某些元素仍保留在VBA环境中。因此,调试/编译找到了该元素,因此缺少某些元素也就不足为奇了。由于项目中没有丢失的东西,因此没有要突出显示的内容,因此只有一条消息,没有其他事情发生。那将解释观察到的行为。

答案 13 :(得分:0)

当代码在该行停止时,我也看到了此错误:

将myNode设置为MSXML2.IXMLDOMNode

我发现我必须通过“工具”>“首选项”添加“ Microsoft XML,v6.0”。

然后它对我有用。

答案 14 :(得分:0)

当我继承另一位分析师的工作簿时,我遇到了同样的问题。他为工作表中的每个按钮分配了宏。当我更改模块名称(而不是过程名称)时,出现了此错误。   修复很容易。让按钮在工作表中运行_OnClick()事件过程,并明确地Call MyProcedureName()使该过程。

答案 15 :(得分:0)

当我在MS Access数据库中出现此错误时,我使用了/ decompile命令行开关以及“压缩/修复”选项。为我工作。 我删除了一个可以确保我的代码不再使用的参考,并开始收到此错误。

答案 16 :(得分:0)

有点晚了,也不是一个完整的解决方案,但对于每个被这个错误击中的人都没有任何明显的原因(定义了所有的引用等)。这个线程让我在正确的轨道上。该问题似乎源自MS Office VBA编辑器中的一些与缓存相关的错误。

对项目进行一些更改后,包括大约40个带有代码模块和40个类的表单以及MS Access 2016中的一些全局模块,编译失败。

注释掉代码显然不是一个选项,导出和重新导入所有80多个文件似乎也不合理。 专注于最近改变的内容,我的怀疑集中在删除一个课程模块。

没有更好的想法我重新制作了一个空类模块,其名称与先前已删除的相同。而voliá错误消失了! 甚至可以在不重新出现错误的情况下再次删除未使用的类模块,直到任何更改保存到以前包含涉及现在删除的类的WithEvents声明的表单模块。

即使在删除声明后,不完全确定WithEvents声明是否确实触发了错误。没有线索如何真正找出(没有关于发展历史的信息)哪个表格可能是罪魁祸首...

但最终解决了这个问题的是:

  1. 在VBE中 - 从表单代码模块中复制所有代码
  2. 在设计视图中的Access打开表单中,将 具有模块 属性设置为
  3. 保存项目(这将删除与表单关联的所有代码)
  4. (不确定是否需要关闭并重新打开Access,但我做到了)
  5. 在设计视图中打开表单,并将 具有模块 属性设置回
  6. 在VBE中粘贴复制的模块代码
  7. 保存

答案 17 :(得分:0)

同一症状的另一个问题:我实现了一个未定义的类。它被#if包裹起来,我认为应该不允许编译器看到它,但不是这样。删除Implements语句中的注释,一切都很好。我假设导入定义也可以...

答案 18 :(得分:0)

我昨天遇到了同样的错误:我的项目中有两个类cProgress和cProgressEx,其中一个不再使用,当我删除了cProgress类时,我得到了同样的编译错误。

我设法修复错误如下:

  • 将所有模块,表单和类导出到硬盘
  • 从项目中删除了所有内容
  • 保存了项目
  • 重新导入所有模块,表单和类,删除cProgress类并编译。
  • 错误消失了。

答案 19 :(得分:0)

多年以后,我发现了Excel中“用户定义类型未定义”错误的Microsoft错误,如果不是,则回答。我正在运行Excel 2010 for Windows。

如果你有一个名为'xyz()'的UDF,那么如果你调用一个以该名称开头的不存在的实体后跟一个句点,后跟其他字符 - 例如,如果你试图调用不存在的范围名称“ xyz.abc ”,那么愚蠢的应用程序会抛出错误的消息,之后它会将你返回到你的工作表。

在我的情况下,它特别令人不安,因为我的UDF只用一个字母命名,例如x()y()等,我也有包含句点的范围名称 - “ x.a ”,“ c.d '等等。每次我拼错一个范围名称 - 例如'x.h'时,引发'用户定义的'错误只是因为一个名为'x()的UDF '存在于我项目的某个地方。

花了几个小时。诊断。以上建议逐步删除项目中的代码,或相反地删除所有代码并逐步添加回来,这些建议都在正确的轨道上,但他们没有遵循。它与代码本身无关;它只与每个proc中第一行代码的名称有关,即命名proc的Sub MyProcFunction MyProc行。当我在项目的一个完全不相关的部分中注释掉我的一个单字母命名的UDF时,出现了错误信息。走了,从那里,又过了一小时。或者说,我能够按规定概括规则。

除了句点('.')之外,标点字符也许会出现错误。但是范围名称中允许的非字母字符数不是很多;允许使用下划线('_'),但以所描述的方式使用它似乎不会引发错误。

Jim Luedke

答案 20 :(得分:0)

晚期绑定

由于缺少引用,可能会发生此错误。例如,当从早期绑定更改为后期绑定时,通过消除引用,某些代码可能会保留引用特定于已删除引用的数据类型。

尝试包含引用以查看问题是否消失。

可能错误不是编译器错误而是链接器错误,因此特定行未知。对微软感到羞耻!