【问题标题】:using classes to work with multiple ranges in excel vba使用类在 excel vba 中处理多个范围
【发布时间】:2015-04-06 15:23:43
【问题描述】:

关于在 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 excel vba


    【解决方案1】:

    我必须在多张纸上处理大范围

    如果您从计算机的角度考虑,您的代码将非常实用。这些范围代表真实的事物(代理、客户、发票、交易),所以请以这些术语来思考。

    我会有一个包含代理所有属性的代理类。我将拥有一个包含所有代理类的代理集合类。然后,在我的 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 属性,该属性返回您正在寻找的客户子集。

    【讨论】:

    • 这太棒了!非常有帮助!除其他外,我不确定类对象的集合是否有意义,即拥有一个代理类,然后将其汇总到一个集合中。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2016-07-19
    • 2018-06-19
    • 2011-04-07
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 2021-05-22
    相关资源
    最近更新 更多