何时使用VBA中的类?

什么时候适合在Visual Basic for Applications(VBA)中使用类?

我假设加速开发和减less引入错误是大多数支持OOP的语言的一个共同的好处。 但是用VBA,有没有特定的标准?

这取决于谁来开发和维护代码。 典型的“超级用户”macros作家黑客小型特设应用程序可能会被类困惑。 但对于严重的发展,使用类的理由与其他语言相同。 你有和VB6一样的限制 – 没有inheritance – 但是你可以通过使用接口来实现多态。

类的一个很好的用法是表示实体和实体的集合。 例如,我经常看到将Excel范围复制到二维数组中的VBA代码,然后使用如下代码处理二维数组:

Total = 0 For i = 0 To NumRows-1 Total = Total + (OrderArray(i,1) * OrderArray(i,3)) Next i 

将范围复制到具有适当命名属性的对象集合中更具可读性,例如:

 Total = 0 For Each objOrder in colOrders Total = Total + objOrder.Quantity * objOrder.Price Next i 

另一个例子是使用类来实现RAIIdevise模式(谷歌为它)。 例如,我可能需要做的一件事是解除工作表的保护,做一些操作,然后再保护它。 使用类可确保工作表将始终受到保护,即使在代码中发生错误时也是如此:

 --- WorksheetProtector class module --- Private m_objWorksheet As Worksheet Private m_sPassword As String Public Sub Unprotect(Worksheet As Worksheet, Password As String) ' Nothing to do if we didn't define a password for the worksheet If Len(Password) = 0 Then Exit Sub ' If the worksheet is already unprotected, nothing to do If Not Worksheet.ProtectContents Then Exit Sub ' Unprotect the worksheet Worksheet.Unprotect Password ' Remember the worksheet and password so we can protect again Set m_objWorksheet = Worksheet m_sPassword = Password End Sub Public Sub Protect() ' Protects the worksheet with the same password used to unprotect it If m_objWorksheet Is Nothing Then Exit Sub If Len(m_sPassword) = 0 Then Exit Sub ' If the worksheet is already protected, nothing to do If m_objWorksheet.ProtectContents Then Exit Sub m_objWorksheet.Protect m_sPassword Set m_objWorksheet = Nothing m_sPassword = "" End Sub Private Sub Class_Terminate() ' Reprotect the worksheet when this object goes out of scope On Error Resume Next Protect End Sub 

然后你可以使用它来简化你的代码:

 Public Sub DoSomething() Dim objWorksheetProtector as WorksheetProtector Set objWorksheetProtector = New WorksheetProtector objWorksheetProtector.Unprotect myWorksheet, myPassword ... manipulate myWorksheet - may raise an error End Sub 

当这个Sub退出时,objWorksheetProtector超出范围,工作表再次被保护。

我认为这个标准和其他语言一样

如果您需要将多个数据和某些方法连接在一起,并且特别处理创build/终止对象时发生的情况,那么类是理想的

比如说你打开一个表单的时候有几个程序会被触发,而其中一个程序需要很长时间,你可能会决定你想要每个阶段的时间……

您可以创build一个秒表类,其中包含明显启动和停止函数的方法,然后您可以添加一个函数来检索到目前为止的时间,并使用表示被定时进程名称的参数在文本文件中进行报告。 你可以编写逻辑来logging最慢的调查performance。

然后,您可以添加一个进度栏对象的方法来打开和closures它,并显示当前行动的名称,以及以毫秒为单位的时间和根据以前存储的报告等可能的剩余时间等

另一个例子是,如果你不喜欢Access的用户组垃圾,你可以创build你自己的用户类,包括login和登出的方法,以及组级别用户访问控制/审计/logging某些动作/跟踪错误等function。

当然,你可以使用一组不相关的方法和大量的variables传递,但要把它封装在一个类中,对我来说似乎更好。

你迟早会接近VBA的限制,但它是一个非常强大的语言,如果你的公司与你联系起来,你实际上可以得到一些好的,复杂的解决scheme。

我不会说有一个特定的标准,但我从来没有真正find一个有用的地方在VBA代码中使用类。 在我看来,它与Office应用程序的现有模型紧密相连,在对象模型之外添加额外的抽象只是混淆了事情。

这并不是说在VBA中找不到一个有用的地方,或者使用一个类来做非常有用的事情,只是我从来没有发现它在这个环境中有用。

处理更复杂的API函数时,类尤其有用,特别是在需要数据结构的时候。

例如,GetOpenFileName()和GetSaveFileName()函数采用带有许多成员的OPENFILENAME结构。 你可能不需要利用所有的优势,但他们在那里,应该初始化。

我喜欢将结构(UDT)和API函数声明封装到CfileDialog类中。 Class_Initialize事件设置了结构成员的默认值,所以当我使用这个类时,我只需要设置我想改变的成员(通过Property程序)。 标志常量以Enum的forms实现。 所以,例如,要select一个电子表格打开,我的代码可能看起来像这样:

 Dim strFileName As String Dim dlgXLS As New CFileDialog With dlgXLS .Title = "Choose a Spreadsheet" .Filter = "Excel (*.xls)|*.xls|All Files (*.*)|*.*" .Flags = ofnFileMustExist OR ofnExplorer If OpenFileDialog() Then strFileName = .FileName End If End With Set dlgXLS = Nothing 

该类将默认目录设置为我的文档,但如果我想我可以使用InitDir属性进行更改。

这只是一个例子,说明一个类如何在VBA应用程序中获得巨大的利益。

您也可以重用VBA代码而不使用实际的类。 例如,如果你有一个被调用的VBACode。 您可以使用以下语法访问任何模块中的任何函数或子文件:

 VBCode.mysub(param1, param2) 

如果你创build了一个对模板/文档的引用(就像你将要做的那样),你可以用同样的方式引用其他项目的代码。

通过使用面向对象编程来开发软件(即使使用Microsoft Access)通常也是一种很好的做法。 通过允许对象松散耦合,以及一些优点,它将允许将来的可伸缩性。 这基本上意味着你的系统中的对象将会减less对方的依赖,所以重构变得容易很多。 您可以使用类模块来实现这个Access。 缺点是你不能在VBA中执行类inheritance或多态。 最后,关于使用类没有硬性规定,只是最佳实践。 但请记住,随着应用程序的增长,维护类更容易。

对于数据recursion(也称为BOM处理),自定义类是非常有帮助的,我认为有时是不可或缺的。 您可以在不使用类模块的情况下创buildrecursion函数,但很多数据问题无法得到有效解决。

(我不知道为什么人们不会为VBA推销BOM库集,也许XML工具已经有所作为了)。

多个表单实例是一个类的常见应用(许多自动化问题否则无法解决),我假设问题是关于自定义类。

当我需要做某事时,我使用类,而一个类将最好的做到这一点:)例如,如果你需要响应(或拦截)事件,那么你需要一个类。 有些人讨厌UDT(用户定义的types),但是我喜欢它们,所以如果我想要简单的英文自我logging代码的话,我会使用它们。 Pharmacy.NCPDP更容易阅读,然后strPhrmNum :)但是UDT是有限的,所以说我想能够设置Pharmacy.NCPDP,并具有所有其他属性填充。 而且我也想做到这一点,所以你不能不小心改变数据。 那么我需要一个类,因为你在UDT中没有只读属性,等等。

另一个考虑是简单的可读性。 如果你正在做复杂的数据结构,知道你只需要调用Company.Owner.Phone.AreaCode然后试图跟踪所有的结构。 尤其是对于那些在离开后2年内必须维护代码库的人:)

我自己的两分钱是“有目的的代码”。 不要没有理由地使用class级。 但是,如果你有一个理由然后做:)

如果我想创build一个自封装的代码包,我将使用类,我将跨越许多VBA项目使用各种客户端。

你可以在访问中定义一个sql包装类,比logging集和querydefs更方便。 例如,如果要根据另一个相关表中的条件更新表,则不能使用连接。 你可以build立一个VBA recorset和querydef来做到这一点,但是我发现一个类更容易。 另外,你的应用程序可能有一些需要更多2个表的概念,使用类可能会更好。 例如您的应用程序跟踪事件。 事件有几个属性,将保存在几个表{用户及其联系人或configuration文件,事件描述; 状态跟踪; 清单帮助支持人员回复事件; 回复…} 为了跟踪所有涉及的查询和关系,oop可以是有帮助的。 能够做Incident.Update(xxx)而不是所有的编码是一种解脱…

我不明白为什么VBA的标准与其他语言有什么不同,尤其是如果你指的是VB.NET。