1

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.

Pᴇʜ
  • 56,719
  • 10
  • 49
  • 73
R. C.
  • 25
  • 4

2 Answers2

0

The Click event of a Frame control is only raised when you click the border of that said frame or its blank area. If you click a Label within a Frame, this control has it's own area. If you click this area, then that's the label's Click event that is raised, not the frame's.

The followin picture shows you the area that belongs to the Label (grey) vs the area that belong to the Frame (red).

Read area = Frame click event

CharlesPL
  • 331
  • 1
  • 10
  • Thank you, I appreciate it. But how would I connect the click event of the Label with the click event of its Frame? I would like the user to be able to click the Frame OR the label and for both to be selected (and other Frames in the user form group to be deselected if need be). How should I connect them all? Like how [this answer](https://stackoverflow.com/questions/19280524/raising-event-from-object-in-custom-collection-class) suggests? It feels like there's an easier solution for me, or am I just not used to classes? – R. C. Apr 08 '19 at 16:46
  • Inside the label's `Click` event, organise a way get to its parent `Frame` [like this](https://stackoverflow.com/a/49771731/10397847), then call this frame Click sub. – CharlesPL Apr 08 '19 at 17:15
0

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
EvR
  • 3,418
  • 2
  • 13
  • 23