create array of existing buttons vb 2013 - arrays

I used to program in VB6 and am trying to write the same program in VB 2013. In this program I use an array of 49 buttons that all do the same thing when you click on them. I have figured out have to do the click function to a point:
Private Sub Button_Click(sender As Object, e As EventArgs) Handles Button9.Click, Button10.Click, Button11.Click, Button12.Click, Button13.Click, Button16.Click, Button17.Click, Button18.Click, Button19.Click, Button20.Click
...
End Sub
What I am trying to do is simplify the code down to using an array so I can just pass on the index. One other person asked the same question in 2010 and the best answer was:
Button[] array = { firstButton, secondButton };
That would work but I want something with less typing. I also tried the following with failure:
One
Button[] buttons = this.Controls.OfType<Button>().ToArray();
Two
For i = 1 To 100
Dim btns() As Button = Controls.Find("Button" & i, True)
Dim btn As Button
If btns IsNot Nothing Then
btn = btns(0)
'If buttons Is Nothing Then
' ReDim buttons(0)
'Else
' ReDim Preserve buttons(buttons.Length)
'End If
'buttons(UBound(buttons)) = btn
btn.Text = i - 1 'here you can change whatever you want
End If
Next
Three
Dim buttons() As Button
buttons = Nothing
For Each b As Button In Me.Controls
If buttons Is Nothing Then
ReDim buttons(0)
Else
ReDim Preserve buttons(buttons.Length)
End If
buttons(UBound(buttons)) = b
Next
I just can't get it to accept the existing buttons into an array. I hope someone can help.

If your Buttons are nested inside container controls (e.g. a GroupBox) then you will need to perform a recursive search for all buttons. Maybe something like this (totally unoptimized)...
Private Function FindAllButtons(root As Control) As List(Of Button)
Dim result As List(Of Button) = New List(Of Button)()
For Each c As Control In root.Controls
If TypeOf c Is Button Then
result.Add(DirectCast(c, Button))
ElseIf c.HasChildren Then
result.AddRange(FindAllButtons(c))
End If
Next
Return result
End Function
Then just call that in your Form:
Dim allButtons as List(Of Button) = FindAllButtons(Me)
' Add common Click handler
For Each b As Button In allButtons
AddHandler b.Click, AddressOf Button_Click
Next
Update Just for fun, here's a generic version to find other types of control.
Private Function FindAllControls(Of T As Control)(root As Control) As List(Of T)
Dim result As List(Of T) = New List(Of T)()
For Each c As Control In root.Controls
If TypeOf c Is T Then
result.Add(DirectCast(c, T))
ElseIf c.HasChildren Then
result.AddRange(FindAllControls(Of T)(c))
End If
Next
Return result
End Function
You can use that like:
Dim allButtons As List(Of Button) = FindAllControls(Of Button)(Me)
Dim allTextBoxes As List(Of TextBox) = FindAllControls(Of TextBox)(Me)

Option two will work, you just need to add the button found into a list. I suggest you add your buttons into a List(Of ) instead of an array. You can always convert the list into an array if you really need to.
Dim buttonList As New List(Of Button)
For i As Integer = 1 To 100
Dim btns() As Control = Controls.Find("Button" & i, True)
If btns IsNot Nothing AndAlso btns.Length > 0 Then
buttonList.Add(CType(btns(0), Button))
End If
Next

Related

How to Create a filter/drop down menu in VBA with user input

currently my code prompts the user to enter a comma separated list of titles. However, is there a way i can change the code so instead the user can search for the title desired from a drop down menu, click a checkbox by the title, and able to keep searching for required titles until done. And store these strings in an array.
Dim arWords() As String
myt = InputBox("Enter User Input")
arWords() = Split(myt, ",")
For X = 0 To UBound(arWords)
myf = myf & arWords(X) & vbNewLine
Next X
I have an array (arrH) later in the code that has all the titles stored so i think id have to use this as the source, if i need one?. Or so i believe. Im still learning.
arrH = Split(arrTxt(HeaderRow), vbTab)
Thanks!
Create a UserForm.
"the user can search for the title desired from a drop down menu, click a checkbox by the title, and able to keep searching for required titles until done".
UserForm with a ComboBox & CheckBox. On CheckBox_Change event, have the script store the value of ComboBox to a public module-level array and iterate the array index.
Have a "Done" button that hides the userform.
Here's what the Userform code module looks like:
Public SelectedTitles As Variant, ArrCount As Long, EnableEvents As Boolean
Private Sub CheckBox1_Change()
'User has indicated they want to add the currently selected item to the list
If Not EnableEvents Then Exit Sub
If ArrCount = 0 Then 'First item, create the array
SelectedTitles = Array("")
Else
ReDim Preserve SelectedTitles(UBound(SelectedTitles) + 1) 'Next items, add one more space in the array
End If
'Add the selected title to the array
SelectedTitles(ArrCount) = ComboBox1.Value
'Increment the counter
ArrCount = ArrCount + 1
'Reset the checkbox and the combobox
EnableEvents = False
CheckBox1.Value = False
ComboBox1.Value = ""
EnableEvents = True
End Sub
Private Sub CommandButton1_Click()
'Done Button
Me.Hide
End Sub
Private Sub UserForm_Initialize()
EnableEvents = True
End Sub
Here is a sub to aid in adding items to a ComboBox list:
Sub ComboBox_AddFromArray(ByRef ComboBox As Object, ListArray As Variant)
ComboBox.Clear
If IsArray(ListArray) Then
Dim i As Long
For i = LBound(ListArray) To UBound(ListArray)
ComboBox.AddItem ListArray(i), ComboBox.ListCount
Next i
Else
ComboBox.AddItem ListArray, 0
End If
End Sub
This function would go after Load UserForm1 and before UserForm1.Show. And you would input the arguments like ComboBox_AddFromArray UserForm1.ComboBox1, arrH.
The way you'd put this all together is by having a controlling function that does all of the Userform processes and then returns what you need, which is that user selected array of titles.
This is what that would look like
Function UserInputForm(ByRef ArrayOfAllTitles As Variant) As Variant
Load UserForm1
ComboBox_AddFromArray UserForm1.ComboBox1, ArrayOfAllTitles
UserForm1.Show
UserInputForm = UserForm1.SelectedTitles
Unload UserForm1
End Function
And Finally, an example of how to include that function into your main sub:
Dim SelectedTitles As Variant
SelectedTitles = UserInputForm(arrH)
'SelectedTitles is now an array of Variant/String values
Dim i As Long
For i = LBound(SelectedTitles) To UBound(SelectedTitles)
Debug.Print SelectedTitles(i)
'Access individual members of the array using SelectedTitles(i)
Next i

VBA: How to use a textbox to search a listbox, select multiple strings, and store selected strings in an Array

I want to apologize ahead of time for how bad at coding i am.
The objective is to create a userform where the user can use the text box to search for movie titles and they will appear in the listbox (enabled multiselect) where the user can select up to multiple movie titles. When this is done they can hit the done button which will compile said strings in an array and exit. I also have a cancel button which can just exit the userform, do i need this?
Here is the code i have thus far, thank you tons
Option Explicit
Private Sub cancelbutton_Click()
End Sub
Private Sub donebutton_Click()
End Sub
Private Sub ListBox1_Click()
End Sub
Private Sub TextBox1_Change()
Dim j As Long, testString As String
testString = "*" & TextBox1.text & "*"
With Me.ListBox1
.Clear
.List = Sheets("HERS Data").Range("A2:J" & Sheets("HERS Data").Cells(Rows.Count, 1).End(xlUp).Row).Value
If .listIndex = -1 And Len(TextBox1.text) Then
For j = .ListCount - 1 To 0 Step -1
If (Not (LCase(.List(j, 0)) Like testString) And (Not (LCase(.List(j, 1)) Like testString))) _
And (Not (LCase(.List(j, 2)) Like testString) And (Not (LCase(.List(j, 3)) Like testString))) Then .RemoveItem j
Next j
End If
End With
End Sub
Private Sub ListBox_AddFromArray(ByRef ComboBox As Object, ListArray As Variant)
ListBox.Clear
If IsArray(ListArray) Then
Dim i As Long
For i = LBound(ListArray) To UBound(ListArray)
ListBox.AddItem ListArray(i), ListBox.ListCount
Next i
Else
ListBox.AddItem ListArray, 0
End If
End Sub
Private Sub CreateArrayFromListbox()
Dim nIndex As Integer
Dim arWords() As Variant
' dimension the array first instead of using 'preserve' in the loop
ReDim arWords(ListBox1.ListCount - 1)
For nIndex = 0 To ListBox1.ListCount - 1
arWords(nIndex) = ListBox1.List(nIndex)
Next
End Sub
Also I have this line in here and I know it does not belong, I know it is using sheets but that does not apply to me as I already Have stored a .txt file (tab delmited) in an array. Sorry hang with me here
.List = Sheets("HERS Data").Range("A2:J" & Sheets("HERS Data").Cells(Rows.Count, 1).End(xlUp).Row).Value
The tab delimited data that I want the user to search from i have stored away in a array
Also, I have this function that calls on the user form in my main code
Function UserInputForm() As Variant()
Load UserForm1
ListBox_AddFromArray UserForm1.ListBox1, arrH
UserForm1.Show
UserInputForm = UserForm1.arWords
Unload UserForm1
End Function
Where arrH has the list of 1000 movie titles i need and arWords is the string list array i wish to take away from it (user selected movies).

add multiple array to corresponding comboboxes

I have several arrays named : Array1, Array2, Array3, ... and also some comboboxes named: cboArray1, cboArray2, cboArray3, ....
How can i write a GENERAL code to add elements of each array to corresponding combox. I know following code works, but its not GENERAL and ABSTRACT.
For i = 0 To Array1.Length - 1
cboArray1.Items.Add(Array1(i))
Next
For i = 0 To Array2.Length - 1
cboArray2.Items.Add(Array2(i))
Next
...
Working procedure maybe as follows: 1. Find all comboboxes in form (easy) 2. extract name of a combox (easy) 3. find similar-named array from code (difficult) 4. ....
I can use other sets like List, ... if it makes sense.
Here's what you're asking for using Reflection...though I'm not sure how useful this really is:
Public Class Form1
Private Array1 As String() = {"cat", "dog", "fish"}
Private Array2 As String() = {"alpha", "beta", "gamma"}
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
WireComboBoxes(Me)
End Sub
Private Sub WireComboBoxes(ByVal container As Control)
For Each ctl As Control In container.Controls
If TypeOf ctl Is ComboBox AndAlso ctl.Name.ToUpper.StartsWith("CBO") Then
Dim cb As ComboBox = DirectCast(ctl, ComboBox)
Dim arrName As String = cb.Name.Substring(3)
Dim fi As System.Reflection.FieldInfo = Me.GetType.GetField(arrName, Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.IgnoreCase)
If Not IsNothing(fi) Then
cb.DataSource = fi.GetValue(Me)
End If
ElseIf ctl.HasChildren Then
WireComboBoxes(ctl)
End If
Next
End Sub
End Class

How to access several dymanically created Combobox at form load?

I'm creating comboboxes on form load, but the thing is once I have added a new cb I can't access (set value, edit properties, etc) of the prior ones.
See Below Example:
Sub Start_stackoverflow()
Dim strings() As String = {"Green", "Purple", "Red"}
Dim x as integer
For x = LBound(strings) To UBound(strings)
NewDropDown(x,50,100,strings(x),strings(x))
Next x
End Sub
Private Sub NewDropDown(ByVal Number As Integer, ByVal PosX As Integer, ByVal PosY As Integer, ByVal Name As String, ByVal Text As String)
cbComboBox = New ComboBox
cbComboBox.Location = New Point(150, PosY - 4%)
cbComboBox.Name = Number
cbComboBox.ForeColor = Color.White
cbComboBox.BackColor = Color.DarkBlue
cbComboBox.Text = Name
cbComboBox.AutoSize = True
Me.Controls.Add(cbComboBox)
End Sub
So this is what happens, I can create the comboboxes just fine, add the values but if I wanted to edit the combobox Green for example (since it was first) I cant.
Even If I try this:
Sub Test()
UpdateComboBoxCurrentlySelected(Green, MyValueIwantSelected)
End Sub
Sub UpdateComboBoxCurrentlySelected(ByVal SetGrpName As ComboBox, ByVal CurrentItem As String)
SetGrpName.Text = (CurrentItem)
SetGrpName.SelectedText = (CurrentItem)
SetGrpName.SelectedItem = (CurrentItem)
SetGrpName.SelectedIndex = (CurrentItem)
SetGrpName.SelectedValue = (CurrentItem)
End Sub
Can anyone shed some light on this, that way I will know how to do it properly.
Thanks
You either need to hold a reference to the object you want to edit:
' At form level
Private dropdowns As Dictionary(Of String, Combobox) = New Dictionary(Of String, ComboBox)
' Populate from Sub Start_stackoverflow()
Dim dropdown As ComboBox = Nothing
' ...
dropdown = NewDropDown(x,50,100,strings(x),strings(x))
dropdowns.Add(dropdown.Name, dropdown)
' change UpdateComboBoxCurrentlySelected signature to
Sub UpdateComboBoxCurrentlySelected(ByVal SetGrpName As String, ByVal CurrentItem As String)
' get the dropdown by name
Dim dropdown as ComboBox = dropdowns(SetGrpName)
' ...
Or you can iterate over all the controls in the form looking for the one with the name you asked for.
Dim foundControl As ComboBox = Nothing
For Each control As Control In Me.Controls
If control.GetType Is GetType(ComboBox) AndAlso (control.Name = SetGrpName) Then
foundControl = control
End If
Next
If Not Nothing Is foundControl Then
' Do something with your control.
End If

Visual Basic Click Event Adding Scores together

Not 100% sure how to do this, mainly because I am new to programming here!
I have created a table which is populated with random numbers from an array, when the user clicks on one of the buttons the number needs to be added onto their score. eg, when a user clicks 10 and 15, their score will be 25. Once the user has clicked on the button, the button needs to change colour To AliceBlue (just a random colour). Any advice / examples?
This code below makes the table which is used within the game,
Let me know what you think!
Dim RandomNumbers = Enumerable.Range(0, 100).ToList()
Dim RandomNumber As New Random()
For Me.TableColunm = 0 To 4 Step 1
For Me.TableRow = 0 To 4 Step 1
Dim TemporaryNumber = RandomNumbers(RandomNumber.Next(0, RandomNumbers.Count))
RandomNumbers.Remove(CInt(TemporaryNumber))
TableButtons = New Button()
With TableButtons
.Name = "TextBox" & TableColunm.ToString & TableRow.ToString
.Text = TemporaryNumber.ToString
.Width = CInt(Me.Width / 4)
.Left = CInt(TableColunm * (Me.Width / 4))
.Top = TableRow * .Height
.Tag = TemporaryNumber
AddHandler TableButtons.Click, AddressOf TableClickEvent
End With
GameScreen.Controls.Add(TableButtons)
Next TableRow
Next TableColunm
Catch ex As Exception
MsgBox(ex.StackTrace & vbCrLf & "index1= " & TableColunm & vbCrLf & "index2= " & TableRow)
End Try
and
Public Sub TableClickEvent(sender As Object, e As EventArgs)
CType(sender, Button).BackColor = Color.BlueViolet
OverAllScoreInteger += CInt(CType(sender, Button).Tag)
End Sub
I also have to parse the score into a text box called 'UserScoreBox' the form is on 'GameScreen'
You add an eventhandler to a control by using the AddHandler statement and providing the sub that handles the event.
Private Sub Clickhandler(sender As Object, e As EventArgs)
CType(sender, Button).BackColor = Color.AliceBlue
End Sub
Sender is basically the source that initiated the event. In this case the button you clicked.
To make the button raise the event, add this to the code where you create the Buttons:
Addhandler TableButtons.Click, AddressOf Clickhandler
To add the scores you can for example place the index of the table row the button represents to the .Tag property of the button. That way you can, in the event handler, retrieve the row of the sender and add the values.
Edit: Adding the number:
On button creation, save the number in the tag (You could also just use the .Text, but doesn't really matter, it's one conversion less this way):
With TableButtons
.Tag = Temporarynumber
And in the handler unpack the object again:
Overallscore += CInt(CType(sender, button).Tag)

Resources