Dynamically Added SpinButtons

Multiverse

New Member
Joined
Nov 15, 2019
Messages
16
Hi

I've been working on a UserForm which loads in data from a Worksheet range, and dynamically creates a varying number of TextBoxes. I now want to dynamically add a SpinButton to each line I'm displaying in the form. The SpinButton will increment or or reduce the value of a line by a penny (or a cent). How should I handle the SpinButton _Change() Sub when the number of buttons will be dynamic?

This is how I've created the buttons:

VBA Code:
    For i = 3 To PostingsLastRow
        n = n + 1
        Set cSpinButton = FormInvoice.FrameInvLines.Controls.Add("Forms.SpinButton.1")
        With cSpinButton
            .Name = "SpinButton" & n
            .Orientation = fmOrientationHorizontal
            .Height = 15
            .Width = 50
            .Left = 940
            .Top = p
        End With
        p = p + 20
    Next i

I've uploaded an image so you can see when I'm going with this.

Many thanks!
 

Attachments

  • demo.png
    demo.png
    6.8 KB · Views: 13

Excel Facts

How to find 2nd largest value in a column?
MAX finds the largest value. =LARGE(A:A,2) will find the second largest. =SMALL(A:A,3) will find the third smallest
First, insert a class module...

VBA Code:
Visual Basic Editor >> Insert >> Class Module

Then, in the Properties window under Name, give it the name clsSpinButton, and then enter the following code in the class module (customize the change event accordingly)...

Code:
Option Explicit

Public WithEvents MySpinButton As MSForms.SpinButton

Private Sub MySpinButton_Change()
    MsgBox MySpinButton.Name & " = " & MySpinButton.Value
End Sub

Then, in the userform code module, enter the following code...

Code:
Option Explicit

Dim spinButtonCollection As Collection

Private Sub UserForm_Initialize()
    Set spinButtonCollection = New Collection
   
    Dim cSpinButton As clsSpinButton
    Dim ctrl As Control
    For Each ctrl In Me.Controls
        If TypeName(ctrl) = "SpinButton" Then
            Set cSpinButton = New clsSpinButton
            Set cSpinButton.MySpinButton = ctrl
            spinButtonCollection.Add cSpinButton
        End If
    Next ctrl
End Sub

Hope this helps!
 
Upvote 0
Hi!

This deffo helps! Thanks ever so much. I hadn't considered using a class was the way to go for this task. Can I ask... why does this code only work on initialize?

What I'm trying to do is have a frame that display invoice information. One SpinButton will iterate through invoices and bring each new invoice into the frame replacing the last one. Each invoice line has a SpinButton for each line to adjust rounding differences. I can't get the Spinbuttons created after initialize to work.

Thanks again for your help. Greatly appreciated
.
OnInitialize.png
NewInvoice.png
 
Upvote 0
Actually, each time a spinbutton is dynamically created, you can create a new instance of clsSpinButton, and add it to spinButtonCollection. So, you'll still have the class module, which defines our new class object. And, you'll still declare spinButtonCollection at the top of your userform code module. But then, instead of using the initialize event, you would amend your original code as follows. Note that for clarity I've changed the name of the variable that gets assigned a newly created spinbutton from cSpinButton to newSpinButton. Then I've declared cSpinButton as clsSpinButton to assign a new instance of our class object.

Code:
    Set spinButtonCollection = New Collection

    Dim cSpinButton As clsSpinButton
    Dim newSpinButton As MSForms.SpinButton
    Dim i As Long
    Dim n As Long
    Dim p As Long
    
    p = 25 'change the starting top position as desired
    For i = 3 To PostingsLastRow
        n = n + 1
        Set newSpinButton = FormInvoice.FrameInvLines.Controls.Add("Forms.SpinButton.1")
        With newSpinButton
            .Name = "SpinButton" & n
            .Orientation = fmOrientationHorizontal
            .Height = 15
            .Width = 50
            .Left = 940
            .Top = p
        End With
        Set cSpinButton = New clsSpinButton
        Set cSpinButton.MySpinButton = newSpinButton
        spinButtonCollection.Add cSpinButton
        p = p + 20
    Next i

Does this help?
 
Upvote 0
Don't forget to set the spinButtonCollection to nothing when the form terminates...
 
Upvote 0
Don't forget to set the spinButtonCollection to nothing when the form terminates...
Why? I may have missed something, but I don't see a circular reference, as far as I can see the GC would have no issue with the code above - what have I missed?
 
Upvote 0
I agree there is no circular reference between the classes, but it is a good idea to set collections to nothing anyway.
 
Upvote 0
Are you one of the camp that set everything to Nothing then? Or is there something about collections?

I’m afraid I’m in the opposite camp ;)
 
Upvote 0
No i'm not strict about it, unless it's about collections of class instances, then I tend to set them to nothing once I'm done with them.
 
Upvote 0
@Domenec Thanks ever so much. That code works perfectly.

Now that the spinButtons are working, the dynamic textboxes won't update as I want them to. When I debug.print their values, they have changed, but not on the form. Updating static textboxes works fine. Does this mean I have to create a class for my dynamic textboxes as well?

Many thanks
 
Upvote 0

Forum statistics

Threads
1,215,219
Messages
6,123,690
Members
449,117
Latest member
Aaagu

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top