4

我正在使用“工作表抽象\工作表代理”技术开发一个 Excel VBA 项目,在没有工作表文章和我的问题中的后续问题中进行了描述。我的 VBA 代码采用 MVP 设计模式构建,并且我编写了尽可能多的 OOP 代码。Rubberduck 的“代码检查”功能在此过程中提供了很大的帮助,但是在最近的版本中(我认为自 v2.4.1.4*** 起,但不能完全确定确切的版本)我开始一直得到一些我不太明白的“Rubberduck Opportunities”和“Code Quality Issues”警告。

如标题所述,第一个是Member 'x' has a 'VB_VarHelpID' attribute with value '-1', but no corresponding annotationRubberduck 机会。每当我在“WorksheetProxy”类中声明一个事件公开工作表(或其他事件公开对象,即命令按钮)时,我都会得到这个。以下代码中的两行都会触发此错误:

' This code sits in my ProcessMasterProxy class
Private WithEvents sheet As Worksheet
Private WithEvents buttonHideOwnerToAvailability As CommandButton

然后,每当我声明暴露事件的“SheetProxy”类的实例或暴露事件的 UserForm 时,我都会在“Presenter”类中得到相同的错误:

' Here I am declaring an instance of the ProcessMasterProxy class from the above snippet
Private WithEvents assetPrx As ProcessMasterProxy
Private WithEvents view As ChecklistPopup

Rubberduck 的代码检查为此类错误提供了两种操作:1.“添加属性注释”'@MemberAttribute VB_VarHelpID, -1在声明上方插入行和 2.“删除属性”似乎什么都不做,单击后错误仍然存​​在。

我想知道“添加属性注释”修复对我的 VBA 项目有什么影响,以及我是否应该应用它,或者更确切地说要更改我的代码中的某些内容以避免完全出错。

同样,我担心我在“代码质量问题”部分中遇到的一个相关错误:To the variable 'sheet' of declared type 'EXCEL.EXE:Excel.Worksheet' a value is set assigned with the incompatible declared type 'ProcessMgmt.ProcessMaster'这与上面第一个片段中的“ProcessMasterProxy”类中的以下代码有关:

Private WithEvents sheet As Worksheet
Private WithEvents buttonHideOwnerToAvailability As CommandButton

Private Sub Class_Initialize()
    ***Set sheet = ProcessMaster***
    Set buttonHideOwnerToAvailability = ProcessMaster.btnHideAssetOwnerToAvailability
End Sub

其中“ProcessMaster”是实际 Excel 工作表的名称,上述代码位于其相应的“SheetProxy”类中。

Code Inspections 针对此错误提供的唯一选项是“忽略一次”,我想知道这样做是否安全。我之前在几个项目中出现过这个错误,但那里一切正常。但是,在我最近的项目中,我在打开工作簿时开始随机收到“运行时错误 35010”,其中我的 Workbook_Open 事件中有以下代码:

Private pres As Presenter
If pres Is Nothing Then
    Set pres = New Presenter
End If

此问题是否与上述两个代码检查建议/错误中的任何一个有关?

4

1 回答 1

5

这些检查的作用是显示 VBE 可能添加的隐藏属性。通常,这些属性会影响类的使用方式(VB_Exposed, VB_PredeclaredId)或成员的行为方式(VB_UserMemId等)。但是它们在编辑器中也是完全不可见的,并且没有相应的注释/注释,通常无法分辨它们的存在。

检查结果为

在这种特殊情况下,Rubberduck通知1变量上有一个隐藏VB_VarHelpId属性。WithEvents

通过添加相应的注解注释,我们使隐藏代码在编辑器中可见和可修改:更改注解的参数值,Rubberduck 检查现在会说属性和注解不同步,这意味着隐藏的代码说明了一件事,但可见的评论在说另一个。

删除属性应该具有将模块导出到临时文件、修改该文件以删除隐藏属性并将修改后的模块重新导入项目的效果。请注意,由于无法以这种方式将文档模块(例如 ThisWorkbook 或工作表模块)导入项目,这在文档模块中不起作用,因此 Rubberduck 不应警告这些模块中的注释/属性不同步。如果 quickfix 没有做任何事情,请报告错误,因为这绝对可以!(编辑:确认使用构建 2.4.1.5229 按预期工作)

归根结底,“Rubberduck 机会”检查就是:利用 Rubberduck 特定功能的机会(例如管理隐藏属性的注释注释):它们并不表示代码有任何问题。


“不兼容类型”检查结果是一个已知问题:目前 Rubberduck 没有看到Worksheet工作表模块的接口(也没有看到 的Workbook接口ThisWorkbook),这导致了文档模块周围的一些误报。直到 Rubberduck 能够分辨出ProcessMaster它不仅是一个ProcessMaster对象而且还是一个Worksheet(我们将在 2.5.x 中对此进行修复),当它抱怨文档模块和 MSForms 接口(它们具有相同的底层)时,忽略该检查可能是安全的问题)。

这种检查背后的想法是,通常 VBA 只会在运行时意识到对象类型不兼容,但是(假设它看到所有类型的所有接口)Rubberduck 可以在设计时告诉你一个问题,远远超过的执行。


至于间歇性错误,我怀疑这是因为您在对象实际可用之前访问它们。Initialize您的类的处理程序在该New Presenter语句处运行,然后调用返回对 assign 的引用pres

我会尝试看看将代码从Initialize处理程序移动到一些参数化初始化程序中是否可以解决它。

If pres Is Nothing Then
    Set pres = New Presenter
    pres.Initialize ProcessMaster
End If

Initialize过程可能如下所示(未经测试):

Public Sub Initialize(ByVal masterSheet As Worksheet)
    Set sheet = masterSheet
    Set buttonHideOwnerToAvailability = masterSheet.Buttons("btnHideAssetOwnerToAvailability")
End Sub

这个想法是,注入工作表依赖而不是将它耦合到演示者类(这是一件非常好的事情!),但主要是让类实例在我们开始访问主机文档之前完全初始化自己(它刚刚打开并且可能有一些尚未完成的异步初始化......只是在这里大声思考,这可能是也可能不是实际发生的事情)。


1可以在设置中配置每个单独检查的严重性级别。

于 2019-12-13T14:00:58.527 回答