Create textboxes on userform on runtime

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Create textboxes on userform on runtime

Post by YasserKhalil »

Hello everyone
I am trying to create textboxes on userform on runtime and this is the code

Code: Select all

Private Sub UserForm_Initialize()
    Dim ctl As Control, sWord As String, xLen As Long, i As Long
    sWord = "Hello World"
    xLen = Len(sWord)
    For i = 1 To xLen
        Set ctl = Me.Controls.Add("Forms.TextBox.1", "ctl", True)
        With ctl
            .Top = 20
            .Left = ((i - 1) * 20) + 20
            .Height = 30
            .Width = 25
            .Font.Size = 14
            .TextAlign = fmTextAlignCenter
            .Text = Mid(sWord, i, 1)
        End With
    Next i
End Sub
How can I skip the space in the word string and to leave a space (no textbox) ?
I mean as for the space to take the same height and width on userform but no textbox at this point.

And how can I adjust the width of the userform according to the created textboxes?
I noticed also that aligning text to center doesn't work properly ..!

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

Centering text boxes is not perfect. Moreover, the text boxes are too narrow to center the text. See what happens if you make them wider:

Code: Select all

Private Sub UserForm_Initialize()
    Const w = 60 ' Change as needed, but not too small
    Dim ctl As Control, sWord As String, xLen As Long, i As Long
    sWord = "Hello World"
    xLen = Len(sWord)
    For i = 1 To xLen
        If Mid(sWord, i, 1) <> " " Then
            Set ctl = Me.Controls.Add("Forms.TextBox.1", "ctl" & i, True)
            With ctl
                .Top = 20
                .Left = i * w
                .Height = 30
                .Width = w
                .Font.Size = 14
                .TextAlign = fmTextAlignCenter
                .Text = Mid(sWord, i, 1)
            End With
        End If
    Next i
    Me.Width = (i + 1) * w + 10
End Sub
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

Amazing my tutor. That's perfect.
Thank you very much
Do you remember an issue of putting random asterisk ..? How can I be able to put random dashes or asterisks for some letters?

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

Why don't you combine the code you have for that with the code for the userform?
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

I will try but in fact I feel lost when trying to deal with too much code. But I promise I will try to do my best.

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

I thought it is difficult to modify it. I copied the public procedure and stored the variable of the word string as you did. Changed asterisk to dash and loop through the new jumbled word and now it is working very well.
To be clear I ma trying to create a missing letter puzzle so I thought of using userform which I see better and more appropraite
How can now I navigate using TAB on only the textboxes which has the dashes.?
I mean to set focus on the first textbox which has the first dash to let the student fill the missing letter and when he typed a letter the cursor move to the next textbox with the dash till the end

Code: Select all

Private Sub UserForm_Initialize()
    Const w As Integer = 40
    Dim ctl As Control, sWord As String, xLen As Long, i As Long
    sWord = "Hello World"
    
    Dim n As Long, m As Long, p() As Long, j As Long, k As Long, l As Long, t As Long
    n = Len(sWord)
    m = Round(0.25 * n, 0)
    For i = 1 To n
        If Mid(sWord, i, 1) <> " " Then
            j = j + 1
            ReDim Preserve p(1 To j)
            p(j) = i
        End If
    Next i
    For i = 1 To 5
        For k = 1 To j
            l = Application.RandBetween(1, j)
            t = p(k)
            p(k) = p(l)
            p(l) = t
        Next k
    Next i
    For i = 1 To m
        Mid(sWord, p(i), 1) = "-"
    Next i
    xLen = Len(sWord)
    For i = 1 To xLen
        If Mid(sWord, i, 1) <> " " Then
            Set ctl = Me.Controls.Add("Forms.TextBox.1", "ctl" & i, True)
            With ctl
                .Top = 20
                .Left = i * w
                .Height = 30
                .Width = w
                .Font.Size = 14
                .TextAlign = fmTextAlignCenter
                .Text = Mid(sWord, i, 1)
            End With
        End If
    Next i
    Me.Width = (i + 1) * w + 10
End Sub

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

Just above End With, insert

Code: Select all

                If Mid(sWord, i, 1) <> "-" Then
                    .TabStop = False
                End If
This excludes the letters from the tab order.
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

Amazing. Thank you very much for this pretty trick.
last point: after the student fill the missing letters, I would like to display a message box to display if he filled the letters correcly or not.

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

You'd have to store the original string in a module-level variable, and compare the characters in that variable to those in the text boxes...
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

In standard module I put this

Code: Select all

Public sNewWord As String
and in userform put this

Code: Select all

Private Sub UserForm_Initialize()
    Const w As Integer = 40
    Dim ctl As Control, sWord As String, xLen As Long, i As Long
    
    sWord = "Hello World"
    sNewWord = sWord
    
    Dim n As Long, m As Long, p() As Long, j As Long, k As Long, l As Long, t As Long
    n = Len(sWord)
    m = Round(0.25 * n, 0)
    For i = 1 To n
        If Mid(sWord, i, 1) <> " " Then
            j = j + 1
            ReDim Preserve p(1 To j)
            p(j) = i
        End If
    Next i
    For i = 1 To 5
        For k = 1 To j
            l = Application.RandBetween(1, j)
            t = p(k)
            p(k) = p(l)
            p(l) = t
        Next k
    Next i
    For i = 1 To m
        Mid(sWord, p(i), 1) = "-"
    Next i
    
    xLen = Len(sWord)
    
    For i = 1 To xLen
        If Mid(sWord, i, 1) <> " " Then
            Set ctl = Me.Controls.Add("Forms.TextBox.1", "ctl" & i, True)
            With ctl
                .Top = 20
                .Left = i * w
                .Height = 30
                .Width = w
                .Font.Size = 14
                .TextAlign = fmTextAlignCenter
                .Text = Mid(sWord, i, 1)
                If Mid(sWord, i, 1) <> "-" Then
                    .TabStop = False
                End If
            End With
        End If
    Next i
    Me.Width = (i + 1) * w + 10
End Sub

What I am stuck at is to how to compare what's in the textboxes in that case with the sNewWord variable?
How can I do that?

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

Something like

Code: Select all

    Dim i As Long
    Dim f As Boolean
    ' Initially, assume that everything is correct.
    f = True
    ' Loop through the characters
    For i = 1 to Len(sNewWord)
        ' We don't have to check the spaces, so we skip those
        If Mid(sNewWord, i, 1) <> " " Then
            ' If the text box doesn't match the character ...
            If Me.Controls("ctl" & i) <> Mid(sNewWord, i, 1) Then
                ' ... set f to False and get out
                f = False
                Exit For
            End If
        End If
    Next i
    ' Everything still correct?
    If f Then
        MsgBox "Congratulations, you guessed right!", vbInformation
    Else
        MsgBox "Sorry, that's not entirely correct!", vbCritical
    End If
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

Sorry for the question but where exactly I could put this code ..?
I have put it into command button to test and it works well
But I need to create the command button in the middle at the bottom of the text boxes and in that case I would like to learn how to put code to such created button?
Last edited by YasserKhalil on 18 Sep 2020, 11:01, edited 1 time in total.

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

For example in the On Click event procedure of a command button on the userform.
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

I was modifying my previous reply ..

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

Creating code on the fly is not a good idea - it requires that the user gives permission to access the VBA code project.
I would place the command button on the userform manually, then move it to the desired position in the UserForm_Initialize event.
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

OK my tutor. How can I move the command button to be placed in the center at the bottom of the created textboxes?

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

You know how to do that - use the width of the userform and the width of the command button to calculate the desired Left position of the command button.

S3527.png
You do not have the required permissions to view the files attached to this post.
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

Do you mean like that

Code: Select all

Me.CommandButton1.Left = (Me.Width / 2) - (Me.CommandButton1.Width / 2)

User avatar
HansV
Administrator
Posts: 78235
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Create textboxes on userform on runtime

Post by HansV »

Yes, indeed. Or, equivalently

Me.CommandButton1.Left = (Me.Width - Me.CommandButton1.Width) / 2
Best wishes,
Hans

YasserKhalil
PlatinumLounger
Posts: 4911
Joined: 31 Aug 2016, 09:02

Re: Create textboxes on userform on runtime

Post by YasserKhalil »

Thanks a lot. Thank you very much my tutor for the awesome help
This is the final code for those who follow the thread

Code: Select all

Dim sNewWord As String, tmp As Control

Private Sub CommandButton1_Click()
    Dim f As Boolean, i As Long
    f = True
    For i = 1 To Len(sNewWord)
        If Mid(sNewWord, i, 1) <> " " Then
            If UCase(Me.Controls("ctl" & i)) <> UCase(Mid(sNewWord, i, 1)) Then
                f = False: Exit For
            End If
        End If
    Next i
    If f Then
        MsgBox "Congratulations, You Guessed Right!", vbInformation
    Else
        MsgBox "Sorry, That Is Not Entirely Correct!", vbCritical
    End If
    If Not tmp Is Nothing Then tmp.SetFocus
End Sub

Private Sub UserForm_Initialize()
    Const w As Integer = 40
    Dim ctl As Control, f As Boolean, sWord As String, xLen As Long, i As Long
    sWord = "Hello World"
    sNewWord = sWord
    xLen = Len(sWord)
    sWord = RandomDashes(sWord)
    For i = 1 To xLen
        If Mid(sWord, i, 1) <> " " Then
            Set ctl = Me.Controls.Add("Forms.TextBox.1", "ctl" & i, True)
            With ctl
                .Top = 20
                .Left = i * w
                .Height = 30
                .Width = w
                .Font.Size = 14
                .TextAlign = fmTextAlignCenter
                .Text = Mid(sWord, i, 1)
                If f = False And Mid(sWord, i, 1) = "-" Then f = True: Set tmp = ctl
                If Mid(sWord, i, 1) <> "-" Then
                    .TabStop = False
                End If
            End With
        End If
    Next i
    Me.Width = (i + 1) * w + 10
    Me.CommandButton1.Left = (Me.Width - Me.CommandButton1.Width) / 2
    If Not tmp Is Nothing Then
        With tmp
            .SetFocus
            .SelStart = 0
            .SelLength = Len(.Text)
        End With
    End If
End Sub

Function RandomDashes(ByVal s As String)
    Dim n As Long, m As Long, p() As Long, i As Long, j As Long, k As Long, l As Long, t As Long
    n = Len(s)
    m = Round(0.25 * n, 0)
    For i = 1 To n
        If Mid(s, i, 1) <> " " Then
            j = j + 1
            ReDim Preserve p(1 To j)
            p(j) = i
        End If
    Next i
    For i = 1 To 5
        For k = 1 To j
            l = Application.RandBetween(1, j)
            t = p(k)
            p(k) = p(l)
            p(l) = t
        Next k
    Next i
    For i = 1 To m
        Mid(s, p(i), 1) = "-"
    Next i
    RandomDashes = s
End Function