小编Cri*_*use的帖子

x64 自定义类上的 For Each 枚举错误

几个月前我在 VBA 中发现了一个错误,但找不到合适的解决方法。这个错误真的很烦人,因为它限制了一个很好的语言功能。

使用自定义集合类时,通常希望有一个枚举器,以便可以在For Each循环中使用该类。这可以通过添加以下行来完成:

Attribute [MethodName].VB_UserMemId = -4 'The reserved DISPID_NEWENUM
Run Code Online (Sandbox Code Playgroud)

紧接在函数/属性签名行之后:

  1. 导出类模块,在文本编辑器中编辑内容,然后重新导入
  2. 在函数签名上方使用Rubberduck注释'@Enumerator然后同步

不幸的是,在 x64 上,使用上述功能会导致写入错误的内存并在某些情况下导致应用程序崩溃(稍后讨论)。

重现错误

CustomCollection 班级:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "CustomCollection"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private m_coll As Collection

Private Sub Class_Initialize()
    Set m_coll = New Collection
End Sub
Private Sub Class_Terminate()
    Set m_coll = Nothing
End …
Run Code Online (Sandbox Code Playgroud)

excel 64-bit vba enumeration custom-collection

20
推荐指数
1
解决办法
612
查看次数

在大型项目上使用接口时出现错误

对于较大的 VBA 项目(40,000 多行代码),我无法正确使用接口,因为应用程序(我主要使用 Excel)会经常崩溃。显然,这是因为代码不能保持编译状态(根据我的理解,VBA 代码被编译为 P 代码,稍后解释)。当 VBA 项目受密码保护时,我主要会得到这种行为。

当我打开托管文档时,调试/编译菜单几乎从不“变灰”:
在此处输入图片说明

文章描述了同样的情况。转至第 2.3 节

例如:
IClass接口:

Option Explicit

Public Property Get SomeProperty() As Double
End Property
Run Code Online (Sandbox Code Playgroud)

Class1

Option Explicit

Implements IClass

Private Property Get IClass_SomeProperty() As Double
    IClass_SomeProperty = 0
End Property
Run Code Online (Sandbox Code Playgroud)

标准模块中的代码:

Option Explicit

Sub TestInterface()
    Dim obj As IClass
    
    Set obj = New Class1
    Debug.Print obj.SomeProperty 'Crashes here on large projects only
End Sub
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,Debug.Print obj.SomeProperty如果项目很小,该行可以正常工作并在“立即”窗口中打印 0。但是,在大型项目中,调用此行时应用程序会崩溃。在IClass_SomeProperty没有达到(记录到文件阐明了这一点)。

正如上面提到的文章,有一些方法可以暂时避免这个问题:

  1. 重新编译解决了问题(并非总是如此),但在下次打开文档时可能会发生崩溃,或者它可能会持续几天(假设文件每天都打开)
  2. When …

vba interface implements

14
推荐指数
1
解决办法
321
查看次数

缓慢的“属性获取”和“函数”过程

我遇到了一个令人讨厌的 VBA 错误,它使Property Get过程调用变得非常慢。这很可能是由于最近的 Office 更新(我有 Office365)造成的。它仅影响 32 位 CPU 上的 Excel。

错误

考虑一个Class1仅使用代码调用的类:

Option Explicit

Public Property Get Something() As Long: End Property
Run Code Online (Sandbox Code Playgroud)

基本上,一个Get返回零的属性。

运行以下代码时(在标准 .bas 模块中):

Public Sub TestSpeed()
    Const iterations As Long = 10000
    Dim i As Long
    Dim t As Double
    Dim coll As New Collection
    '
    t = Timer
    For i = 1 To iterations
        coll.Add New Class1
        CallGet coll.Item(coll.Count)
    Next i
    Debug.Print iterations & " loops took " …
Run Code Online (Sandbox Code Playgroud)

excel vba

5
推荐指数
1
解决办法
479
查看次数