HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

VBA Python-like List Class

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
likepythonvbalistclass

Problem

VBA's Collection class is lacking so I created a basic List class using Python's as a template. This could make future derived classes easier to implement.

The biggest features are better setting and accessing of values. But one neat-o feature is Python-style indexing.

Dim myList As List
myList.Extend(Array(1,2,3,4,5,6))
Debug.Print myList(-2) ' 5
Debug.print myList.Slice(-1, 1).ToString '"[6,5,4,3,2,1]"


Note: I kept VBA's 1 offset for collections. This means that there is a hole at index 0 and will always return subscript out of range. I don't like it but this way List's will play nice with VBA's collection objects.

Private members

Option Explicit
Private collec As Collection ' Sole datamember


TransformIndex: Enforces Zero Offset and Cylcing.

Private Sub TransformIndex(ByRef x As Variant)
    If x < 0 Then x = x + collec.Count + 1
End Sub


Replace is private; use Item and Slice to actually replace elements

Private Sub Replace(ByVal index As Long, ByVal element As Variant)

    collec.Remove index

    If index = collec.Count + 1 Then
        collec.Add element
    Else
        collec.Add element, before:=index
    End If

End Sub


Some boring stuff

Private Sub Class_Initialize()
    Set collec = New Collection
End Sub
Private Sub Class_Terminate()
    Set collec = Nothing
End Sub
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4

    Set NewEnum = collec.[_NewEnum]

End Property


Public Methods

The general pattern for these is and implementation of one action for a single element and another for a sequence of elements. e.g. Item and then Slice or Append and Extend. The only exception is removal that only implements single elements.

Accessers and Replacement

Item and Slice provide general access to members and allows replacement as they are not read only.

```
Public Property Let Item(ByVal index As Long, ByVal element As Variant)
Attribute Item.VB_UserMemId

Solution

I'm no VBA coder so just a few minor things:

-
Is there a particular reason to use ByRef for the parameter to TransformIndex? It doesn't seem exactly necessary and I usually prefer methods without side effects.

-
collec reads clumsy. I would rename it to something like underlying or underlyingCollection.

-
You should take a bit more care naming method parameters. Parameter names form an important part of the method documentation and should convey their intent clearly. For example here it is not exactly clear what a and b mean:

Public Sub Clear(ByVal a As Long, ByVal b As Long)


-
For Clear it is not entirely clear if for example the end index is included or not for the removal. C# usually follows the convention of specify the start index and the count of how many elements should be removed (i.e. Clear(start, count)). I found that approach more robust in the long run.

-
I don't think dumping the entire list content in ToString() is all that useful, especially if the list can grow larger it could be problematic.

Code Snippets

Public Sub Clear(ByVal a As Long, ByVal b As Long)

Context

StackExchange Code Review Q#62963, answer score: 5

Revisions (0)

No revisions yet.