Search code examples
excelvbauserform

Connecting events of controls inside frame to FrameGroup classes


I have a UserForm that reads data from a file and dynamically fills a Frame control with other Frame controls that themselves are filled with Labels describing that data. So, there's one big Frame control — DisplayFrame — put onto the UserForm using the Toolbox, and at runtime when the file is opened other smaller Frame controls — cFrame1, cFrame2, etc — are added inside the DisplayFrame control, with labels like NameLabel, DateLabel, added to each cFrame.

I'd like the user to be able to select any of the cFrames, then click a button on the user form and for another window to open with all of the data inside the labels (plus additional data) in that cFrame.

By select, I mean that when the user clicks on ANY of the labels inside a particular cFrame — or the cFrame itself — the color of the cFrame and all its elements change and that particular cFrame is recorded as being the current selection. The tricky part, I think, is that the color of any previously selected cFrame should change back to the default color.

I've created a Class called FrameGroup to hold all the cFrames that are created. I defined the click event of the FrameGroup class to change color when it is selected and to hold the data of the cFrame just selected.

<<Class FrameGroup>>
Public WithEvents FrameGroup As Frame

Private cName As String
Private cDay As String

Private Sub FrameGroup_Click()
    cName = FrameGroup.Controls(0).Caption
    cDay = FrameGroup.Controls(1).Caption

    ' If current cFrame was selected before, then deselect it 
    ' by returning to default color
    If FrameGroup.BackColor = &H8000000D Then
        FrameGroup.BackColor = &H80000005
        FrameGroup.Controls(0).BackColor = &H80000005
        FrameGroup.Controls(1).BackColor = &H80000005
    Else
       ' Select cFrame by changing color
        FrameGroup.BackColor = &H8000000D
        FrameGroup.Controls(0).BackColor = &H8000000D
        FrameGroup.Controls(1).BackColor = &H8000000D
    End If
End Sub
<<Code for UserForm>>
Dim FrameList() As New FrameGroup

Private Sub UserForm_Initialize()
    Dim TextLine As String
    Dim Text() As String
    Dim LineNo As Integer

    ' Open file containing saved Color Scales
    Open file For Input As #1

    LineNo = 0
    Do Until EOF(1)
        Line Input #1, TextLine
        Text = Split(TextLine, ",")

        ' Making CFrame
        Dim currCFrame As Frame
        Set currCFrame = DisplayFrame.Controls.Add("Forms.Frame.1", "cFrame" & LineNo, True)

        ' Adding labels
        Dim NameLabel As Control
        Set NameLabel = currCFrame.Controls.Add("Forms.Label.1", "Name" & LineNo, True)
        Dim DateLabel As Control
        Set DateLabel = currCFrame.Controls.Add("Forms.Label.1", "DateCreated" & LineNo, True)

        ' Increment line number
        LineNo = LineNo + 1

        ' Adding new frame to frame group
        ReDim Preserve FrameList(1 To LineNo + 1)
        Set FrameList(LineNo).FrameGroup = currCFrame

    Loop

    ' Close file once we are done reading color scales from it
    Close #1


End Sub

What happens is that only when the cFrame is clicked does anything happen--not when any of the labels inside are clicked. And I don't know how to make it so that when a cFrame is clicked, the color of the previously selected cFrame is also changed to the default color.

I've tried to look up how to do something like this, and solutions like this seem to bring up a different class module for cFrame and its labels and a intermediary class handling communications between two classes, but this seems complicated. If I followed this design, I'd probably need another intermediary between cFrame and the button being clicked to load data, right? I don't want to make this more complicated than it needs to be, but I also would like to create a sustainable and robust solution. Any help would be appreciated.


Solution

  • Label Click put in and clicking in another frame gives the other frames the default color, Tried to minimize the adjustments to your code below:

      '<<Class FrameGroup>>
        Public WithEvents FrameGroup As MSForms.Frame
        Public WithEvents LabelGroup As MSForms.Label
        Private cName As String
        Private cDay As String
    
        Private Sub FrameGroup_Click()
        Dim ctl As MSForms.Control
            cName = FrameGroup.Controls(0).Caption
            cDay = FrameGroup.Controls(1).Caption
             For Each ctl In FrameGroup.Parent.Controls
                ctl.BackColor = &H80000005
             Next
                FrameGroup.BackColor = &H8000000D
                FrameGroup.Controls(0).BackColor = &H8000000D
                FrameGroup.Controls(1).BackColor = &H8000000D
        End Sub
    
        Private Sub LabelGroup_Click()
        Dim ctl As MSForms.Control
            cName = LabelGroup.Parent.Controls(0).Caption
            cDay = LabelGroup.Parent.Controls(1).Caption
            For Each ctl In LabelGroup.Parent.Parent.Controls
                ctl.BackColor = &H80000005
            Next
                LabelGroup.Parent.BackColor = &H8000000D
                LabelGroup.Parent.Controls(0).BackColor = &H8000000D
                LabelGroup.Parent.Controls(1).BackColor = &H8000000D
        End Sub
    
    
        '<<Code for UserForm>>
        Dim FrameList() As New FrameGroup
    
        Private Sub UserForm_Initialize()
            Dim TextLine As String
            Dim Text() As String
            Dim LineNo As Integer
    
            ' Open file containing saved Color Scales
           Open file For Input As #1
    
            LineNo = 0
            Do Until EOF(1)
                Line Input #1, TextLine
                Text = Split(TextLine, ",")
    
                ' Making CFrame
                Dim currCFrame As Frame
                Set currCFrame = DisplayFrame.Controls.Add("Forms.Frame.1", "cFrame" & LineNo, True)
    
                ' Adding labels
                Dim NameLabel As Control
                Set NameLabel = currCFrame.Controls.Add("Forms.Label.1", "Name" & LineNo, True)
                Dim DateLabel As Control
                Set DateLabel = currCFrame.Controls.Add("Forms.Label.1", "DateCreated" & LineNo, True)
    
                ' Increment line number
                LineNo = LineNo + 1
    
                ' Adding new controls to frame group
                ReDim Preserve FrameList(1 To 3 * (LineNo + 1))
                Set FrameList(3 * (LineNo) + 1).FrameGroup = currCFrame
                Set FrameList(3 * (LineNo) + 2).LabelGroup = DateLabel
                Set FrameList(3 * (LineNo) + 3).LabelGroup = NameLabel
    
            Loop
    
            ' Close file once we are done reading color scales from it
            Close #1
    
        End Sub