arrays - Excel VBA 编译错误参数在遍历附加到类集合的数组时不是可选的

标签 arrays excel vba collections compiler-errors

在循环访问附加到存储在集合中的类 Event 的 Team/Group 数组时,我不断收到错误“编译错误:参数不是可选的”

它在行处给出编译错误,因为它没有将对象视为数组:

For ctr = LBound(evt.Team) To UBound(evt.Team)
For ctr = LBound(evt.Group) To UBound(evt.Group)

但是当我直接打印它引用它工作的索引时......就像这一行:
Debug.Print evt.Team(0)
Debug.Print evt.Group(1)

我的要求很简单。
  • Excel Data 读取数据并将每个事件存储在一个集合中以供进一步处理
  • Team 和 Group 数组被添加到 Event 类中,它们仅存储团队详细信息及其各自适用的(标记为“Y”)组

  • 到目前为止,这工作正常,数据存储在 Event Collection适本地。

    当我尝试迭代集合并尝试遍历 Team 和 Group 数组时,就会出现问题。

    事件模块代码
    Option Explicit
    
    Dim ws As Excel.Worksheet
    Dim colEvents As Collection
    Dim hdrRow1, hdrRow2, startRow, startCol, lastRow, lastCol
    Dim startTeam, endTeam, startGroup, endGroup
    Dim ctr, ctrRow, ctrCol
    
    Sub Main()
        Set ws = ThisWorkbook.Sheets("Events")
        Set colEvents = New Collection
    
    With ws
        lastRow = (.UsedRange.Rows.Count)
        lastCol = (.UsedRange.Columns.Count)
        'Debug.Print "Last Row: " & lastRow & " - " & "Last Column: " & lastCol
    
        hdrRow1 = 1
        hdrRow2 = 2
        startRow = 3
        startCol = 1
        startTeam = 4
        endTeam = 6
        startGroup = 7
        endGroup = 11
    
        'Get Groups
        For ctrRow = startRow To lastRow
            Dim oEvent As clsEvent
            Set oEvent = New clsEvent
    
            'Get No, Name, Type
            oEvent.No = .Cells(ctrRow, startCol)
            oEvent.Name = .Cells(ctrRow, startCol + 1)
            oEvent.EType = .Cells(ctrRow, startCol + 2)
    
            'Get Team Details
            ctr = 0
            For ctrCol = startTeam To endTeam
                oEvent.Team(ctr) = .Cells(ctrRow, ctrCol).Value
                ctr = ctr + 1
            Next
    
            'Get Group Details
            ctr = 0
            For ctrCol = startGroup To endGroup
                If (.Cells(ctrRow, ctrCol).Value = "Y") Then
                    oEvent.Group(ctr) = .Cells(hdrRow2, ctrCol).Value
                    ctr = ctr + 1
                End If
            Next
    
            colEvents.Add oEvent
        Next
    End With
    
    'Check Collection
    Dim evt As clsEvent
    For Each evt In colEvents
        Debug.Print "No: " & evt.No
        Debug.Print "Name: " & evt.Name
        Debug.Print "Type: " & evt.EType
    
        'Loop through Team array
        Debug.Print "Team Details: "
        For ctr = LBound(evt.Team) To UBound(evt.Team)
            Debug.Print evt.Team(ctr)
        Next
    
        'Loop through Group array
        Debug.Print "Group Details"
        For ctr = LBound(evt.Group) To UBound(evt.Group)
            Debug.Print evt.Group(ctr)
        Next
    Next
    End Sub
    

    类模块事件
    Option Explicit
    
    Private pNo As Integer
    Private pName As String
    Private pEType As String
    Private pTeam(2) As Integer
    Private pGroup() As String
    
    'Prop No
    Public Property Get No() As Integer
        No = pNo
    End Property
    
    Public Property Let No(ByVal vNewValue As Integer)
        pNo = vNewValue
    End Property
    
    'Prop Events
    Public Property Get Name() As String
        Name = pName
    End Property
    
    Public Property Let Name(ByVal vNewValue As String)
        pName = vNewValue
    End Property
    
    'Prop Event Type
    Public Property Get EType() As String
        EType = pEType
    End Property
    
    Public Property Let EType(ByVal vNewValue As String)
        pEType = vNewValue
    End Property
    
    'Prop Type
    Public Property Get Team(ByVal index As Long) As Integer
        Team = pTeam(index)
    End Property
    
    Public Property Let Team(ByVal index As Long, ByVal vNewValue As Integer)
        pTeam(index) = vNewValue
    End Property
    'Prop Group
    Public Property Get Group(ByVal index As Long) As String
        Group = pGroup(index)
    End Property
    
    Public Property Let Group(ByVal index As Long, ByVal vNewValue As String)
        If (Not pGroup) = -1 Then
            ReDim Preserve pGroup(0)
        End If
        If (index > UBound(pGroup)) Then ReDim Preserve pGroup(index)
        pGroup(index) = vNewValue
    End Property
    
    Private Sub Class_Initialize()
        'statements
    End Sub
    
    Private Sub Class_Terminate()
        'statements
    End Sub
    

    最佳答案

    Team不是数组,这就是 VBA 不将其视为一个数组的原因。
    Team (和 Group )是索引属性。他们正在抽象出封装数据存储在数组中的事实。对于调用代码,数据还不如存储在 Collection 中。 , 一个 Dictionary , 一个 ArrayList , 一个 HashSet ....它根本没有区别:给定一个索引,该属性能够检索并返回一个项目。

    通常,您在自定义集合类上公开索引属性 - 并且将此类属性与其他成员一起公开,例如 Count , Add , 和 Clear .

    但这不是自定义集合类。

    因此,解决方案可能是公开 TeamCountGroupCount属性(property)。请注意,公开 UBound(pTeam)UBound(pGroup)会让你的抽象成为一个漏洞,如果你后来决定你宁愿拥有一个 Collection 可能会导致问题。保存封装的数据。

    Public Property Get TeamCount() As Long
        TeamCount = UBound(pTeam) + 1 '<~ array is zero-based, so count is +1
    End Property
    
    Public Property Get GroupCount() As Long
        If UBound(pGroup) >= 0 Then '<~ would be -1 if uninitialized
            GroupCount = UBound(pGroup) + 1
        End If
    End Property
    

    然后你可以这样做:
    For ctr = 0 To evt.TeamCount - 1
    

    请注意,这仍然是一个泄漏的抽象:封装数组的从零开始的性质到处都是。

    一个更好的抽象将使它能够工作:
    For Each t In evt.Teams
    

    有几种方法可以实现这一点 - 这是最简单的(也可能是性能最低的):
    Public Property Get Teams() As Collection
        Dim result As Collection
        Set result = New Collection
        Dim i As Long
        For i = LBound(pTeams) To UBound(pTeams)
            result.Add pTeams(i)
        Next
        Set Teams = result
    End Property
    

    关于arrays - Excel VBA 编译错误参数在遍历附加到类集合的数组时不是可选的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58174989/

    相关文章:

    javascript - 将数组分配为映射中的对象值

    excel - Excel错误1004 'No cells were found '

    windows - 有没有办法将 Excel 电子表格嵌套在另一个 Excel 电子表格中?

    java - JXL 解决#VALUE 问题

    vba - 在 VBA 中向上舍入到最接近的较大整数

    excel - 将 Excel 4 宏转换为 VBA

    excel - 将 Excel 表数据传输到 SQL 2008R2 的最快方法

    ios - 仅使用索引检索多个数组的值

    arrays - 这行代码在 Julia 编程语言中意味着什么

    iphone - 从 SearchBar 查询执行 NSRange 后抛出的异常