关于在 VBA 中使用简单类的机制,有几个非常好的答案:When to use a Class in VBA?和 What are the benefits of using Classes in VBA?
作为一个对 OOP 和类相对陌生的人,很难知道如何实现它们,甚至很难知道什么是真正可能的。
例如,我必须处理多个工作表中的大范围,并且需要获取数据的许多不同子集。 “做 x 的代理”和“做 y 的客户”...等等。这是我整理的一个子项目,用于了解拥有 2 个以上客户的代理数量:
Sub agent_subset(output_sheet As String, _
Input_sheet_name As String, _
email_col As Integer, _
vendor_count_col As Integer, _
client_count_col As Integer, _
modified_col As Integer, _
num_of_clients As Integer)
' get a list of all agents with 2 or more clients and put them into a sheet
Application.DisplayStatusBar = True
Dim sheet_rows As Long
sheet_rows = Worksheets(Input_sheet_name).Cells(rows.Count, 1).End(xlUp).Row
Dim email_range As Range ' range of agent emails
Dim client_count_range As Range ' range of client count
Dim vendor_count_range As Range ' range of vendor count
Dim modified_range As Range ' range of modified at
With Worksheets(Input_sheet_name)
Set email_range = .Range(.Cells(2, email_col), .Cells(sheet_rows, email_col))
Set client_count_range = .Range(.Cells(2, client_count_col), .Cells(sheet_rows, client_count_col))
Set vendor_count_range = .Range(.Cells(2, vendor_count_col), .Cells(sheet_rows, vendor_count_col))
Set modified_range = .Range(.Cells(2, modified_col), .Cells(sheet_rows, modified_col))
End With
Dim n As Long
Dim counter As Long
counter = 0
Dim modified_array() As String
For n = 2 To sheet_rows
If client_count_range(n, 1).Value > num_of_clients Then
counter = counter + 1
Worksheets(output_sheet).Cells(counter + 1, 1).Value = email_range(n, 1).Value
Worksheets(output_sheet).Cells(counter + 1, 2).Value = client_count_range(n, 1).Value
Worksheets(output_sheet).Cells(counter + 1, 3).Value = vendor_count_range(n, 1).Value
modified_array() = Split(modified_range(n, 1).Value, "T")
Worksheets(output_sheet).Cells(counter + 1, 4).Value = modified_array(0)
End If
Application.StatusBar = "Loop status: " & n & "of " & sheet_rows
Next n
Worksheets(output_sheet).Cells(counter + 3, 1).Value = "Last run was " & Now()
Application.StatusBar = False
End Sub
效果很好,但现在我想根据其他标准获得更小的代理和客户子集。因此,我将编写一个类似的函数,操作类似的数据。我的直觉告诉我,使用类(class)会让我的生活更轻松,但我不知道如何分解任务。
是否应该有一个 Agent 类来包含有关代理的所有信息?和/或客户类别?或者,这些类应该用于查看整个范围或工作表吗?
我不是在寻找特定的代码,而是在寻找一种如何分解事物的方法。
最佳答案
I have to deal with large ranges in multiple sheets
如果您从计算机的角度思考,您的代码将非常实用。这些范围代表真实的事物(代理、客户、发票、交易),所以请用这些术语来思考。
我将有一个代理类来保存代理的所有属性。我将有一个代理集合类来保存我所有的代理类。然后,在我的 Agents 类中,我将拥有返回 Agents 类子集的 Filter 方法。
这是一个例子:我有客户。客户可以是活跃的,也可以是非活跃的。客户还有一个模板,当我通过电子邮件向他们发送某些信息时可以使用该模板。当我想向使用 Table1 模板的活跃客户发送电子邮件时,它看起来像这样
Set clsCustomersToEmail = clsCustomers.FilterOnActive(True).FilterOnTemplate("Table1")
For Each clsCustomer in clsCustomersToEmail
'Do stuff
Next clsCustomer`
在我的 CCustomers 集合类中,我有几个属性返回一个 CCustomers 类,该类的客户数量比大的 CCustomers 类(称为 clsCustomers)少
Public Property Get FilterOnActive() As CCustomers
Dim clsReturn As CCustomers
Dim clsCustomer As CCustomer
Set clsReturn = New CCustomers
For Each clsCustomer In Me
If clsCustomer.Active Then
clsReturn.Add clsCustomer
End If
Next clsCustomer
Set FilterOnActive = clsReturn
End Property
Public Property Get FilterOnTemplate(ByVal sTemplate As String) As CCustomers
Dim clsReturn As CCustomers
Dim clsCustomer As CCustomer
Set clsReturn = New CCustomers
For Each clsCustomer In Me
If clsCustomer.Template.TemplateName = sTemplate Then
clsReturn.Add clsCustomer
End If
Next clsCustomer
Set FilterOnTemplate = clsReturn
End Property
当我想做一些事情,比如将一堆客户数据写入某个范围时,我会创建一个返回数组的属性,并将该数组写入该范围。
Set clsCustomersPastDue = clsCustomers.FilterOnActive(True).FilterOnPastDue(True)
vaWrite = clsCsutomerPastDue.AgingReport
rCell.Resize(UBound(vaWrite,1),UBound(vaWrite,2)).Value = vaWrite
我倾向于思考我正在编码的物理事物。它们不一定是有形的东西,但如果你能把它带回有形的东西,那会很有帮助。
交易是一个事物。但如果该交易是发票,现在确定该对象的属性就变得很容易。首先,您只需查看纸质发票即可了解其属性。
下一个层次是关系。每个代理类别都有客户。因此,您的 Agent 对象应该有一个返回 CCustomers 类的 Customers 属性。或者,如果它在现实生活中的结构不那么严格,也许您的 CCustomers 类有一个 FilterOnAgent 属性,该属性返回您正在查找的客户子集。
关于class - 在 Excel VBA 中使用类处理多个范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29474204/