Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Code So That Intellisense Follows The Complete Chain

Tags:

vba

While this code works and I can assign and retrieve values across all levels, intellisense only displays the methods or properties 1 level deep. How would I go about coding this so that I can follow my "Path" all the way down using intellisense and not necessarily have to just remember the methods or properties?

for instance if I type Wip. I get
Intellisense Showing Methods/Properties

but when I type Wip.Parts("Test"). , the SequenceNumbers member and its Methods/Properties are not displayed No Intellisense Menu

I have the following code

clsSeq:

Option Explicit
Private iSeq As String
Private iQty As Double

Public Property Get Qty() As Double
    Qty = iQty
End Property

Public Property Let Qty(lQty As Double)
    iQty = lQty
End Property

Public Property Get Sequence() As String
    Sequence = iSeq
End Property

Public Property Let Sequence(lSeq As String)
    iSeq = lSeq
End Property

clsPart:

Option Explicit

Private iPart As String
Public SequenceNumbers As Collection

Public Property Get PartNumber() As String
    PartNumber = iPart
End Property

Public Property Let PartNumber(lPart As String)
    iPart = lPart
End Property

Public Sub AddSequence(aSeq As String, aQty As Double)
    Dim iSeq As clsSeq
        If SeqExists(aSeq) Then
            Set iSeq = SequenceNumbers.Item(aSeq)
            iSeq.Qty = iSeq.Qty + aQty
        Else
            Set iSeq = New clsSeq
            With iSeq
                .Sequence = aSeq
                .Qty = aQty
            End With
            SequenceNumbers.Add iSeq, iSeq.Sequence
        End If
        Set iSeq = Nothing
End Sub

Private Sub Class_Initialize()
    Set SequenceNumbers = New Collection
End Sub


Private Function SeqExists(iSeq As String) As Boolean
    Dim v As Variant
        On Error Resume Next
        v = IsObject(SequenceNumbers.Item(iSeq))
        SeqExists = Not IsEmpty(v)
End Function

clsParts:

Option Explicit

Public Parts As Collection

Public Sub AddPart(iPart As String)
    Dim iPrt As clsPart
        If Not PartExists(iPart) Then
            Set iPrt = New clsPart
            With iPrt
                .PartNumber = iPart
            End With
            Parts.Add iPrt, iPrt.PartNumber
        End If
End Sub

Private Function PartExists(iPT As String) As Boolean
    Dim v As Variant
        On Error Resume Next
        v = IsObject(Parts.Item(iPT))
        PartExists = Not IsEmpty(v)
End Function


Private Sub Class_Initialize()
    Set Parts = New Collection
End Sub

modTest:

Sub TestWipCls()
    Dim Wip As clsParts
    Dim Part As clsPart

        Set Wip = New clsParts
        Wip.AddPart ("Test")
        Set Part = Wip.Parts("Test")
        Part.AddSequence "Proc7", 1505
        Debug.Print Wip.Parts("Test").SequenceNumbers("Proc7").Qty
        Part.AddSequence "Proc7", 100
        Debug.Print Wip.Parts("Test").SequenceNumbers("Proc7").Qty
End Sub
like image 475
Glenn G Avatar asked Nov 17 '25 03:11

Glenn G


1 Answers

That is because Parts is a Collection and its Default Member Call (or .Item) will return a value/object depending what was stored. While editing your code VBA does not know what kind of value/object is stored in the collection (as this is only established during run-time, eg. late-bound), so it can not give you any Intellisense-suggestions.
To circumvent this, you need a method (property/function) that returns a defined type of value/object (early-bound).
btw. (myCollection.("Foo") is the same as myCollection.Item("Foo"))

The solution is to create a custom collection that returns a value of a defined type.
The following example also explains how to implement a custom Collection so you can use the default member call instead of using .Item.
How to use the Implements in Excel VBA

While we're at it, please never use public variables in classes, make them accessible via Property Let/Set/Get methods!
More on this here: https://rubberduckvba.wordpress.com/2019/07/08/about-class-modules/

Edit:

Example for a custom Collection for classes that implement ICustomElement (Interfaces are explained in the link above)

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "CustomCollectionTemplate"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
'@Folder("Classes")
Option Explicit


Private Type  TCustomCollection
    CustomCollection as Collection
End Type
Dim this as TCustomCollection


Private Sub Class_Initialize()
        Set this.CustomCollection = New Collection
End Sub

Private Sub Class_Terminate()
        Set this.CustomCollection = Nothing
End Sub

Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
    Set NewEnum = this.CustomCollection.[_NewEnum]
End Property

Public Sub Add(ByVal newCustomElement As ICustomElement)
    this.CustomCollection.Add newCustomElement
End Sub

Public Sub Remove(ByVal Index As Long)
    this.CustomCollection.Remove Index
End Sub

Public Function Item(ByVal Index As Long) As ICustomElement
    Set Item = this.CustomCollection.Item(Index)
End Function

Public Function Count() As Long
    Count = this.CustomCollection.Count
End Function

Thanks to M.Doerner & Mathieu Guindeon for the edits/comments

like image 185
L8n Avatar answered Nov 20 '25 13:11

L8n



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!