我想在我的VBA程序中使用类而不是结构,但无法弄明白。以下是我正在做的事情的一个例子,并且会感激任何建议。也许课程不适合这种类型的东西,因为它对我来说似乎不太直观,我不知道。
Option Explicit
Public Type xYear
month(1 To 12) As Double ' Index is the month
End Type
Public Type Company
Name As String
City As String
Sales(2010 To 2020) As xYear ' Index is the year
End Type
Public SuperData(1 To 50) As Company ' An array of companies with monthly sales
Sub Test_Table()
Dim Company1_Name As String
Dim Company1_City As String
Dim Company1_2011_Sales(1 To 12) As Double
Dim Company1_2012_Sales(1 To 12) As Double
Dim Toledo_Sales_Jul_2012 As Double
' Test Data
Company1_Name = "ABC"
Company1_City = "Toledo"
Company1_2011_Sales(7) = 1000
Company1_2012_Sales(7) = 2000
' Copy test data into Structure
SuperData(1).Name = Company1_Name
SuperData(1).City = Company1_City
SuperData(1).Sales(2011).month(7) = Company1_2011_Sales(1) ' Jul 2011 sales
SuperData(1).Sales(2012).month(7) = Company1_2012_Sales(7) ' Jul 2012 sales
' Query the structure
Toledo_Sales_Jul_2012 = City_Sales("Toledo", 7, 2012)
End Sub
Public Function City_Sales(ByRef City As String, ByRef m As Double, ByRef y As Double) As Double
Dim c As Double
For c = LBound(SuperData) To UBound(SuperData)
If City = SuperData(c).City Then
City_Sales = City_Sales + SuperData(c).Sales(y).month(m)
End If
Next
End Function
答案 0 :(得分:1)
我会用四个类来做这些:CCompany和CSale以及两者的集合类。
CCompany:
Private mlCompanyID As Long
Private msCompanyName As String
Private msCity As String
Private mclsSales As CSales
Private mlParentPtr As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(dest As Any, Source As Any, ByVal bytes As Long)
Public Property Set Sales(ByVal clsSales As CSales): Set mclsSales = clsSales: End Property
Public Property Get Sales() As CSales: Set Sales = mclsSales: End Property
Public Property Let CompanyID(ByVal lCompanyID As Long): mlCompanyID = lCompanyID: End Property
Public Property Get CompanyID() As Long: CompanyID = mlCompanyID: End Property
Public Property Let CompanyName(ByVal sCompanyName As String): msCompanyName = sCompanyName: End Property
Public Property Get CompanyName() As String: CompanyName = msCompanyName: End Property
Public Property Let City(ByVal sCity As String): msCity = sCity: End Property
Public Property Get City() As String: City = msCity: End Property
Public Property Get Parent() As CCompanies: Set Parent = ObjFromPtr(mlParentPtr): End Property
Public Property Set Parent(obj As CCompanies): mlParentPtr = ObjPtr(obj): End Property
Private Function ObjFromPtr(ByVal pObj As Long) As Object
Dim obj As Object
CopyMemory obj, pObj, 4
Set ObjFromPtr = obj
' manually destroy the temporary object variable
' (if you omit this step you'll get a GPF!)
CopyMemory obj, 0&, 4
End Function
Private Sub Class_Initialize()
Set mclsSales = New CSales
End Sub
Private Sub Class_Terminate()
Set mclsSales = Nothing
End Sub
CCompanies:
Private mcolCompanies As Collection
Private Sub Class_Initialize()
Set mcolCompanies = New Collection
End Sub
Private Sub Class_Terminate()
Set mcolCompanies = Nothing
End Sub
Public Property Get NewEnum() As IUnknown
Set NewEnum = mcolCompanies.[_NewEnum]
End Property
Public Sub Add(clsCompany As CCompany)
If clsCompany.CompanyID = 0 Then
clsCompany.CompanyID = Me.Count + 1
End If
Set clsCompany.Parent = Me
mcolCompanies.Add clsCompany, CStr(clsCompany.CompanyID)
End Sub
Public Property Get Company(vItem As Variant) As CCompany
Set Company = mcolCompanies.Item(vItem)
End Property
Public Property Get Count() As Long
Count = mcolCompanies.Count
End Property
CSale:
Private mlSaleID As Long
Private mdAmount As Double
Private mlYear As Long
Private mlMonth As Long
Private mlParentPtr As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(dest As Any, Source As Any, ByVal bytes As Long)
Public Property Let SaleID(ByVal lSaleID As Long): mlSaleID = lSaleID: End Property
Public Property Get SaleID() As Long: SaleID = mlSaleID: End Property
Public Property Let Amount(ByVal dAmount As Double): mdAmount = dAmount: End Property
Public Property Get Amount() As Double: Amount = mdAmount: End Property
Public Property Let Year(ByVal lYear As Long): mlYear = lYear: End Property
Public Property Get Year() As Long: Year = mlYear: End Property
Public Property Let Month(ByVal lMonth As Long): mlMonth = lMonth: End Property
Public Property Get Month() As Long: Month = mlMonth: End Property
Public Property Get Parent() As CSales: Set Parent = ObjFromPtr(mlParentPtr): End Property
Public Property Set Parent(obj As CSales): mlParentPtr = ObjPtr(obj): End Property
Private Function ObjFromPtr(ByVal pObj As Long) As Object
Dim obj As Object
CopyMemory obj, pObj, 4
Set ObjFromPtr = obj
' manually destroy the temporary object variable
' (if you omit this step you'll get a GPF!)
CopyMemory obj, 0&, 4
End Function
CSales:
Private mcolSales As Collection
Private Sub Class_Initialize()
Set mcolSales = New Collection
End Sub
Private Sub Class_Terminate()
Set mcolSales = Nothing
End Sub
Public Property Get NewEnum() As IUnknown
Set NewEnum = mcolSales.[_NewEnum]
End Property
Public Sub Add(clsSale As CSale)
If clsSale.SaleID = 0 Then
clsSale.SaleID = Me.Count + 1
End If
Set clsSale.Parent = Me
mcolSales.Add clsSale, CStr(clsSale.SaleID)
End Sub
Public Property Get Sale(vItem As Variant) As CSale
Set Sale = mcolSales.Item(vItem)
End Property
Public Property Get Count() As Long
Count = mcolSales.Count
End Property
Public Sub AddSale(ByVal dAmount As Double, ByVal lYear As Long, ByVal lMonth As Long)
Dim clsSale As CSale
Set clsSale = New CSale
With clsSale
.Amount = dAmount
.Year = lYear
.Month = lMonth
End With
Me.Add clsSale
End Sub
然后在标准模块中。
Sub Test_Class()
Dim clsCompanies As CCompanies
Dim clsCompany As CCompany
Dim clsSale As CSale
Set clsCompanies = New CCompanies
Set clsCompany = New CCompany
clsCompany.CompanyName = "ABC"
clsCompany.City = "Toledo"
'Verbose way to add a sale
Set clsSale = New CSale
clsSale.Amount = 1000
clsSale.Year = 2011
clsSale.Month = 7
clsCompany.Sales.Add clsSale
'Quickway to add a sale
clsCompany.Sales.AddSale 2000, 2012, 7
clsCompanies.Add clsCompany
For Each clsCompany In clsCompanies
For Each clsSale In clsCompany.Sales
Debug.Print clsCompany.CompanyName, clsCompany.City, clsSale.Amount, clsSale.Year, clsSale.Month
Next clsSale
Next clsCompany
End Sub
这使用了一些未记录的功能,例如可以在自定义类上使用For Each。这里有几个参考资料。
http://dailydoseofexcel.com/archives/2010/07/09/creating-a-parent-class/