Initializing all textboxes with a for loop - vba

I have an Initialization for a userform. It works fine when I initialize using the commented out part of the code, but when I use the code as shown below, I get a runtime error 91.
I need a way to loop through or select all textboxes to give them default value, color and etc...
Private Sub UserForm_Initialize()
Dim i As Long
Dim ctl As Control
For i = 1 To 4
ctl = "TextBox" & i
ctl.Value = ""
Next i
'TextBox1.Value = ""
'TextBox2.Value = ""
'TextBox3.Value = ""
'TextBox4.Value = ""
End Sub

In general, to refer to a TextBox of the form, you need Controls("TextboxN). If you want to loop, it is like this - Me.Controls("Textbox" & i), in case that you have not deleted any textboxes and they are following the default order
Thus, this is a possibility:
Private Sub UserForm_Initialize()
Dim i As Long
Dim ctl As Control
For i = 1 To 4
Me.Controls("Textbox" & i) = i
Me.Controls("Textbox" & i).BackColor = vbGreen
Next i
Debug.Print Me.TextBox3.Value
End Sub
With this screenshot, showing each TextBox getting a value of 1,2,3 or 4 and a green color:
Or even this, if you want to make the outlook of the controls a bit different:
Private Sub UserForm_Initialize()
Dim i As Long
Dim ctl As Control
For i = 1 To 4
With Me.Controls("Textbox" & i)
.Value = i
If i Mod 2 = 0 Then
.BackColor = vbBlue
.ForeColor = vbWhite
Else
.BackColor = vbGreen
.BackColor = vbRed
End If
End With
Next i
End Sub
If you are naming the textboxes, following your own programming logic, then looping through the collection of controls and checking the TypeName of the control is a better solution.

make a procedure in normal module:
Sub LoopTxBox()
Dim tb As MSForms.Control
For Each tb In UserForm1.Controls
If TypeName(tb) = "TextBox" Then 'capitalisation matters
'...
End If
Next tb
End Sub
and call it in UserForm_Initialize().

Related

Excel VBA Userform CheckBox check mark does not appear

I have created an UserForm in Excel. The UserForm has a ListBox and a CheckBox added to it.
I have written VBA code to populate the ListBox with data in the 1st column of the UserForm_Data worksheet. I am attempting to add a Select All CheckBox to the UserForm. When I click on the CheckBox once, the check mark does not appear but the If Me.CheckBox.Value = True section of the Checkbox1_Change event is executed and all the items in the ListBox are selected. The check mark appears only when I click the CheckBox the second time. The Excel VBA code and an image of the UserForm are attached.
Option Explicit
Private Sub ListBox1_Change()
Dim i As Long
If CheckBox1.Value = True Then
For i = 0 To Me.ListBox1.ListCount - 1
If Me.ListBox1.Selected(i) = False Then
Me.CheckBox1.Value = False
End If
Next i
End If
End Sub
Private Sub CheckBox1_Change()
Dim i As Long
If Me.CheckBox1.Value = True Then
With Me.ListBox1
For i = 0 To .ListCount - 1
.Selected(i) = True
Next i
End With
Else
i = 0
End If
End Sub
Private Sub UserForm_Initialize()
Dim rng1 As Range
Dim ws1 As Worksheet
Dim i, lastRow As Long
Dim list1 As Object
Dim string1 As String
Dim array1 As Variant
Set list1 = CreateObject("System.Collections.ArrayList")
Set ws1 = ThisWorkbook.Worksheets("UserForm_data")
lastRow = ws1.UsedRange.Rows.Count
Me.ListBox1.Clear
For i = 2 To lastRow
string1 = CStr(ws1.Cells(i, 1).Value)
If Not list1.Contains(string1) Then
list1.Add string1
End If
Next i
array1 = list1.ToArray
Me.Caption = "UserForm1"
Me.ListBox1.list = array1
Me.ListBox1.MultiSelect = 1
Me.CheckBox1.Value = False
End Sub
There are two steps you can take to address this:
There's a chance that simply adding a DoEvents at the end of the CheckBox1_Change event will force the redraw.
If that doesn't work, add the following line just above the DoEvents and test it again... this encourages a screen update...
Application.WindowState = Application.WindowState
One approach is to use global flags to toggle on and off the control event handlers. Here is what the updated events would look like:
Option Explicit
Private Sub ListBox1_Change()
Dim i As Long
If Not AllowListBoxEvents Then Exit Sub
AllowCheckBoxEvents = False
If CheckBox1.Value = True Then
For i = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(i) = False Then CheckBox1.Value = False
Next i
End If
AllowCheckBoxEvents = True
End Sub
Private Sub CheckBox1_Change()
Dim i As Long
If Not AllowCheckBoxEvents Then Exit Sub
AllowListBoxEvents = False
If CheckBox1.Value = True Then
For i = 0 To ListBox1.ListCount - 1
ListBox1.Selected(i) = True
Next i
End If
AllowListBoxEvents = True
End Sub
Make sure you set the "Allow" variables to True in the Initialize event.

Excel Listbox inconsistently has no value after setting the Listindex

I have a simple UserForm with two Listboxes and two Textboxes that contain the value of the currently selected Listitem. I am having a bizarre bug where one of the boxes will not populate when the form loads. If I close the form and load it again, then the opposite box will not load. If I close and reload a third time, then it loads the first box but not the second again. Repeat ad nauseum.
First Load:
Second Load:
The code should have both Textboxes populated at startup. What is the source of this bug?
Private Sub UserForm_Initialize()
Dim i As Long
For i = 1 To 4
ListBox1.AddItem "Item A - " & i
Next i
ListBox1.ListIndex = 0
End Sub
Private Sub ListBox1_Change()
Dim i As Long
ListBox2.Clear
For i = 1 To 3
ListBox2.AddItem "Item B - " & i
Next i
ListBox2.ListIndex = 0
TextBox1.Value = ListBox1.Value
End Sub
Private Sub ListBox2_Change()
TextBox2.Value = ListBox2.Value
End Sub
This answer is from Yow3Ek as much as from anyone. This code runs as tested without error or previous problem. Thanks guys, I learned something today. It was firing on the clear.
Private Sub UserForm_Initialize()
Dim i As Long
For i = 1 To 4
Me.ListBox1.AddItem "Item A - " & i
Next i
Me.ListBox1.ListIndex = 0
End Sub
Private Sub ListBox1_Change()
Dim i As Long
Me.ListBox2.Clear
For i = 1 To 3
ListBox2.AddItem "Item B - " & i
Next i
Me.ListBox2.ListIndex = 0
Me.TextBox1.Value = Me.ListBox1.List(Me.ListBox1.ListIndex)
End Sub
Private Sub ListBox2_Change()
If Me.ListBox2.ListIndex = -1 Then Exit Sub
Me.TextBox2.Value = Me.ListBox2.List(Me.ListBox2.ListIndex)
End Sub

Simplify code with loop

Hi I'm pretty new at the vba so please don't shoot my code :-).
I have a set of repaeting code's. I woukld like to simplify this code by using the code name with an increasing number. I can't get it to run. Can someone help me a bit on the road to get this going.
Below what I'm trying.
The second block is a part of the code now (it's 40 blocks of the same code only increasing the number)
Sub sheet41()
Dim i As Integer
Dim chkname As Integer
chkname = "SheetCheckBox" & i
i = 1
Do
i = i + 1
If chkname.Visible = False Then Exit Sub
If chkname.value = True Then
Sheets("Item_" & i).Select
Call Finalize
End If
Loop Until i = ThisWorkbook.Worksheets.Count
End Sub
This is the old code:
Sub Sheet1()
If SheetCheckBox1.Visible = False Then Exit Sub
If SheetCheckBox1.value = True Then
Sheets("Item_1").Select
Call Finalize
End If
End Sub
Sub Sheet2()
If SheetCheckBox2.Visible = False Then Exit Sub
If SheetCheckBox2.value = True Then
Sheets("Item_2").Select
Call Finalize
End If
End Sub
Sub Sheet3()
If SheetCheckBox3.Visible = False Then Exit Sub
If SheetCheckBox3.value = True Then
Sheets("Item_3").Select
Call Finalize
End If
End Sub
As you can see this should be possible to clean I asume.
This should do it. If finalize isn't called on a worksheet then the reason why is printed to the Immediate Window.
Sub ProcessWorkSheets()
Dim check As MSForms.CHECKBOX
Dim i As Integer
For i = 1 To Worksheets.Count
On Error Resume Next
Set check = Worksheets(i).OLEObjects("SheetCheckBox" & i).Object
On Error GoTo 0
If check Is Nothing Then
Debug.Print Worksheets(i).Name; " - Checkbox not found"
Else
If check.Visible And check.Value Then
Worksheets(i).Select
Call Finalize
Else
Debug.Print Worksheets(i).Name; " - Checkbox", "Visible", check.Visible, "Value:", check.Value
End If
End If
Set check = Nothing
Next
End Sub
If the checkboxes on the Sheet are ActiveX Controls, you can use this to access the checkboxes:
Sheets("sheet1").OLEObjects("chkTest").Object
if you want to change the value of a checkbox, use it like this:
Sheets("sheet1").OLEObjects("chkTest").Object.Value = True
now replace "sheet1" with your actual sheet name and change the "chkTest" to your string chkname
So your complete code should be like this:
Dim i As Integer
Dim sheetname As String
Dim chkname As String
sheetname = "YOUR SHEETNAME HERE"
For i = 1 To ThisWorkbook.Worksheets.Count Step 1
chkname = "SheetCheckBox" & i
If Sheets(sheetname).OLEObjects(chkname).Object.Visible = False Then Exit Sub
If Sheets(sheetname).OLEObjects(chkname).Object.Value = True Then
Sheets("Item_" & i).Select
Call Finalize
End If
Next i

Create event handlers for multiple dynamic controls

I have a userform that creates two dynamic control buttons but I am having difficulty accessing the .name property of the dynamic control, which means I can't create the event handler correctly. Due to this problem I am unable to create event handlers. Below shows the code that creates the dynamic controls and also the code that I have written for the event handlers (which isn't functioning correctly)
Option Explicit
Public WithEvents cButton As MSForms.CommandButton
Private Sub TextBox1_Change()
If TextBox1 <> vbNullString Then
For i = 1 To TextBox1.Value
Set cButton = Me.Controls.Add("Forms.CommandButton.1")
With cButton
.Name = "CommandButton" & i
.Left = 150
.Top = buttonStartPosition
.Width = 300
.Height = 140
End With
Next i
End If
End sub
Private Sub cButton_Click()
If cButton.Name = "CommandButton1" Then
MsgBox "Button1"
ElseIf cButton.Name = "CommandButton2" Then
MsgBox "Button2"
End If
End Sub
Once this code is executed and the two buttons are on the screen, I press the first button (button1) and nothing happens but when I press the second button (button2) I receive the message "Button2". So how come I can't access the first button?
#user3538102 .. To your comment regarding Textbox's. Below is example is an example. I added Combo box select either CommandButton or TextBox and generate events. The code works but could be better.
I added combo box to select to dynamically generate object type.
In UserForm Activate event - Add combo drop down list
Private Sub UserForm_Activate()
ComboBox1.AddItem "CommandButton"
ComboBox1.AddItem "TextBox"
ComboBox1.ListIndex = 0
End Sub
In Class1 Class Module ..
Modified UserForm code ..
Option Explicit
Dim cObjs() As New Class1
Private Sub TextBox1_Change()
Dim i As Integer
Dim buttonStartPosition As Integer
Dim cObj As Object
buttonStartPosition = 30
If TextBox1 <> vbNullString Then
For i = 1 To TextBox1.Value
If ComboBox1.Value = "CommandButton" Then
Set cObj = Me.Controls.Add("Forms.CommandButton.1")
Else
Set cObj = Me.Controls.Add("Forms.TextBox.1")
End If
With cObj
.Name = ComboBox1.Value & i
.Left = 15
.Top = buttonStartPosition
.Width = 30
.Height = 14
End With
ReDim Preserve cObjs(1 To i)
If ComboBox1.Value = "CommandButton" Then
Set cObjs(i).ButtonGroup = cObj
Else
Set cObjs(i).TextGroup = cObj
End If
buttonStartPosition = buttonStartPosition + 14
Next i
End If
End Sub
I got the events for multiple buttons to work with help from .. JWalk Excel Tips
Below is the modification based on your code and the link provided.
Create a Class module called "Class1"
Add modified code to UserForm1..
Option Explicit
Dim Buttons() As New Class1
Private Sub TextBox1_Change()
Dim i As Integer
Dim buttonStartPosition As Integer
Dim cButton As CommandButton
buttonStartPosition = 30
If TextBox1 <> vbNullString Then
For i = 1 To TextBox1.Value
Set cButton = Me.Controls.Add("Forms.CommandButton.1")
With cButton
.Name = "CommandButton" & i
.Left = 15
.Top = buttonStartPosition
.Width = 30
.Height = 14
End With
ReDim Preserve Buttons(1 To i)
Set Buttons(i).ButtonGroup = cButton
buttonStartPosition = buttonStartPosition + 14
Next i
End If
End Sub

How to display Values from a multiselect listbox

I have a form in Excel macro. This form will capture the values inserted in textboxes, listbox and store in Sheet2.
There are 2 buttons in the form applet named "Next" and "Previous". These button will be used for navigating between the saved records. I am able to navigate between records and the values display fine in textboxes. However, I am not sure how can I display the Values from listboxes. My list box is a multiselect list box.
I have provided snippet of my code on how the records are saved in sheet2 and how the navigation happens when clicked on Next button.
Private Sub Save_Click()
Dim ctl As Control
Dim S As String
Dim i As Integer
RowCount = Worksheets("Sheet2").Range("A1").CurrentRegion.Rows.Count
With Worksheets("Sheet2").Range("A1")
.Offset(RowCount, 0).Value = Me.Name1.Value ' capture value from list box
'below code is for capturing value from multiselect listbox
With AOI
For i = 0 To .ListCount - 1
If .Selected(i) = True Then S = S & ", " & .List(i)
Next i
Range("A1").Offset(RowCount, 10).Value = S
End With
End Sub
Below code is for navigating between saved records..
Private Sub Next1_Click()
strCurrentSetofRows = Worksheets("Sheet2").Range("A1").CurrentRegion.Rows.Count
i = i + 1: j = 0
If i > (strCurrentSetofRows - 1) Then
MsgBox "No More Records"
Exit Sub
End If
Set sRange = Worksheets("Sheet2").Range("A1")
Name1.Text = sRange.Offset(i, j).Value: j = j + 1
End Sub
Any thoughts on how can I display saved values of AOI (my field).
Since you are storing the values using , as a separator, you can use the same to split the values and upload it to the ListBox. BTW, I hope you are generating the ListBox with the complete list in the UserForm's Initialize event?
Here is a very basic example. Please amend it to suit your needs.
Let's say Cell A1 has Blah1,Blah2,Blah6. Then try this code
Option Explicit
Dim i As Long, j As Long
Private Sub UserForm_Initialize()
ListBox1.MultiSelect = fmMultiSelectMulti
For i = 1 To 10
ListBox1.AddItem "Blah" & i
Next
End Sub
Private Sub CommandButton1_Click()
Dim ArValues As Variant
Dim sValue As String
Dim multivalues As Boolean
If InStr(1, Range("A1").Value, ",") Then
ArValues = Split(Range("A1").Value, ",")
multivalues = True
Else
sValue = Range("A1").Value
multivalues = False
End If
If multivalues = True Then
For i = 0 To UBound(ArValues)
For j = 0 To ListBox1.ListCount - 1
If ListBox1.List(j) = ArValues(i) Then
ListBox1.Selected(j) = True
Exit For
End If
Next j
Next i
Else
For j = 0 To ListBox1.ListCount - 1
If ListBox1.List(j) = sValue Then
ListBox1.Selected(j) = True
Exit For
End If
Next j
End If
End Sub
Screenshot