用户定义类型与类速度

bla*_*ord 0 vba class user-defined-types

我有一个工作簿,其中包含两个我需要执行操作的数据.我开始直接从工作表中处理数据,但很快就发现它非常慢,所以改变了将工作表读入两个数组(在两个单独的方法中调用Workbook_Open).

我为每张工作表上的数据创建了一个用户定义的类型,然后我发现我无法将这些添加到集合或脚本字典中,因此我将它们转移到了类中.

所以现在我有一个名为CDealerData4个私有字段和公共属性的类.问题是,将数据读入数组的执行时间是我使用类型时的两倍.这是它是怎么回事,或者我做错了什么.

类:

Option Explicit

Private pBAC As String
Private pAccountNumber As String
Private pYear As Integer
Private pUnits As Variant


Public Property Get BAC() As String
    BAC = pBAC
End Property
Public Property Let BAC(Value As String)
    pBAC = Value
End Property


Public Property Get AccountNumber() As String
    AccountNumber = pAccountNumber
End Property
Public Property Let AccountNumber(Value As String)
    pAccountNumber = Value
End Property


Public Property Get Year() As String
    Year = pYear
End Property
Public Property Let Year(Value As String)
    pYear = Value
End Property


Public Property Get Units() As String
    Units = pUnits
End Property
Public Property Let Units(Value As String)
    pUnits = Value
End Property
Option Explicit

Private pBAC As String
Private pAccountNumber As String
Private pYear As Integer
Private pUnits As Variant


Public Property Get BAC() As String
    BAC = pBAC
End Property
Public Property Let BAC(Value As String)
    pBAC = Value
End Property


Public Property Get AccountNumber() As String
    AccountNumber = pAccountNumber
End Property
Public Property Let AccountNumber(Value As String)
    pAccountNumber = Value
End Property


Public Property Get Year() As String
    Year = pYear
End Property
Public Property Let Year(Value As String)
    pYear = Value
End Property


Public Property Get Units() As String
    Units = pUnits
End Property
Public Property Let Units(Value As String)
    pUnits = Value
End Property
Run Code Online (Sandbox Code Playgroud)

模块:

Option Explicit

Public NumberOfYears As Integer

Public DealersData() As CDealerData

Public Sub ReadDealerData()

    '** Reads the contents of RawData into an Array
    '** of custom type DealerData, defined above

    Dim MyDealerData As CDealerData
    Dim LastRow As Long
    Dim i As Long
    Dim j As Long

    LastRow = SheetRawData.UsedRange.Rows.Count

    ReDim DealersData(LastRow * NumberOfYears)

    For i = 0 To LastRow
        For j = 0 To NumberOfYears - 1 'Year columns
            Set MyDealerData = New CDealerData

            MyDealerData.BAC = SheetRawData.Cells(i + 2, 1).Value
            MyDealerData.AccountNumber = SheetRawData.Cells(i + 2, 3).Value
            MyDealerData.Year = j + 1
            MyDealerData.Units = CDec(SheetRawData.Cells(i + 2, 4 + j).Value) 'Assign column based on j

            Set DealersData(i) = MyDealerData
        Next j
    Next i

End Sub
Run Code Online (Sandbox Code Playgroud)

hnk*_*hnk 5

出于多种原因,UDT将比以这种方式使用类快得多.

  1. UDT是内存中的结构,具有可以直接写入的数据
  2. Class将具有Let和Get属性,这些属性是执行并具有一些开销的函数
  3. 创建和销毁类会增加一点开销,但在你的情况下没有什么值得注意的

为了提高性能,您可以考虑使用公共变量而不是私有属性,但是这可能会使您无法使用类的目的.

  • 如果您只想将其用作数据容器,那么最好使用用户定义的数据类型.
  • 如果您希望使用类特定函数进一步操作此数据,则Class方法更好

此外,加快速度的一般方法是尽可能少访问电子表格.

例如,如下的代码

For i = 1 to 10
   Variable = Worksheets("Sheet1").Range("A1").Cell(i,1).Value
Next i
Run Code Online (Sandbox Code Playgroud)

可以替换为

Dim VariantArray as Variant
VariantArray = Workeheets("Sheet1").Range("A1:A10")

' Now VariantArray(0,0) has the first element, (1,0) has the second, etc.
Run Code Online (Sandbox Code Playgroud)

关于分析的说明:请注意@ BlackHawk在下面的评论中的建议,使用MicroTimer工具.它非常有用,可以隔离部分代码并将性能影响发现到非常精确的级别.

此外,虽然对于任何平台都是如此,但VBA性能有时可能会不一致,具体取决于Excel目前的资源压力有多大,因此,即使MicroTimer精确,也可能没有准确的代表性.我想考虑在不同时间运行循环,以正确衡量代码不同部分的影响.