何时在Visual Basic for Applications(VBA)中使用类是否合适?
我假设加速开发和减少引入错误是大多数支持OOP的语言的常见好处.但是对于VBA,是否有具体的标准?
这取决于谁将开发和维护代码.典型的"高级用户"宏编写程序黑客攻击小型ad-hoc应用程序可能会因使用类而感到困惑.但是对于认真的开发,使用类的原因与其他语言相同.你有与VB6相同的限制 - 没有继承 - 但你可以通过使用接口来获得多态性.
类的良好用途是表示实体和实体集合.例如,我经常看到VBA代码将Excel范围复制到二维数组中,然后使用以下代码操作二维数组:
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
另一个例子是使用类来实现RAII设计模式(google for it).例如,我可能需要做的一件事是取消保护工作表,进行一些操作,然后再次保护它.使用类可确保即使代码中发生错误,工作表也将始终再次受到保护:
--- 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超出范围,工作表再次受到保护.
我认为标准与其他语言相同
如果你需要将几个数据和一些方法联系在一起,并且还专门处理在创建/终止对象时发生的事情,那么类是理想的
如果您在打开表单时有一些程序可能会触发,而其中一个程序需要很长时间,您可能会决定要在每个阶段计算......
您可以创建一个秒表类,其中包含用于启动和停止的明显函数的方法,然后您可以添加一个函数来检索到目前为止的时间并使用表示正在计时的进程名称的参数在文本文件中报告它.您可以编写逻辑来仅记录最慢的性能以进行调查.
然后,您可以添加一个进度条对象,其中包含打开和关闭它的方法,并显示当前操作的名称,以及基于先前存储的报告等的ms的时间和剩余的可能时间等
另一个例子可能是,如果您不喜欢Access的用户组垃圾,您可以创建自己的User类,其中包含用于登录和注销的方法以及用于组级用户访问控制/审核/记录某些操作/跟踪错误等的功能
当然你可以使用一组不相关的方法和大量的变量传递来做到这一点,但是将它全部封装在一个类中对我来说似乎更好.
你迟早会接近VBA的极限,但它是一种非常强大的语言,如果你的公司将它与你联系起来,你实际上可以从中获得一些好的,复杂的解决方案.
我不会说有一个特定的标准,但我从来没有真正找到一个在VBA代码中使用Classes的有用位置.在我看来,它与Office应用程序周围的现有模型紧密相关,在该对象模型之外添加额外的抽象只会让事情变得混乱.
这并不是说一个无法找到一个有用的地方在VBA类,或使用类做的非常有用的东西,只是我从来没有发现他们在这种环境中非常有用.
在处理更复杂的API函数时,特别是当它们需要数据结构时,类非常有用.
例如,GetOpenFileName()和GetSaveFileName()函数采用具有许多成员的OPENFILENAME结构.你可能不需要利用所有这些,但它们在那里,应该初始化.
我喜欢将结构(UDT)和API函数声明包装到CfileDialog类中.Class_Initialize事件设置结构成员的默认值,这样当我使用该类时,我只需要设置我想要更改的成员(通过Property过程).标志常量实现为枚举.因此,例如,要选择要打开的电子表格,我的代码可能如下所示:
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
该类将默认目录设置为My Documents,但如果我想,我可以使用InitDir属性更改它.
这只是一个类如何在VBA应用程序中获得巨大益处的一个例子.